英文:
Get-childitem sorted and then delete upon promt input
问题
以下是您要翻译的内容:
-
"i try to sort a list and give it over as variable to then do something with the list. when i run the code without $files (the variable) then it list perfect. when i set the $files in front the output is nothing. what am i doing wrong ? i am very new to powershell and tried since hours to find the right combination, but i seem to not see thru."
我尝试对列表进行排序并将其作为变量传递,然后对列表执行某些操作。当我在不使用$files(变量)的情况下运行代码时,它能够正常列出。但当我在前面设置了$files时,输出为空。我做错了什么?我是PowerShell的新手,已经尝试了几个小时,但似乎无法找到正确的组合。
-
"this code below sorts exactly as wanted, but then delete is not working because $files is nowhere defined i think"
下面的这段代码按照所需的方式排序,但删除操作不起作用,因为我认为$files没有被定义。
-
"i tried this code, but does not even do get-childitem list"
我尝试了这段代码,但甚至没有列出get-childitem的列表。
英文:
i try to sort a list and give it over as variable to then do something with the list. when i run the code without $files (the variable) then it list perfect. when i set the $files in front the output is nothing. what am i doing wrong ? i am very new to powershell and tried since hours to find the right combination, but i seem to not see thru.
this code below sorts exactly as wanted, but then delete is not working because $files is nowhere defined i think
do {
Get-childitem -Path E:\TestEnv\deleted_images\ -recurse -include @("Image*") | Sort-Object -Property LastAccessTime
Group-Object Name -AsHashTable
$files.Values
$userinput = Read-Host -Prompt 'Please Enter Folder name to be deleted'
if ($files.ContainsKey($userinput)) {
$files[$userinput] | Remove-item
Write-Host 'Folder was deleted'
}
}
until([string]::IsNullOrWhiteSpace($userinput))
i tried this code, but does not even do get-childitem list
do {
$files = Get-childitem -Path E:\TestEnv\deleted_images\ -recurse -include @("Image*") | Sort-Object -Property LastAccessTime
Group-Object Name -AsHashTable
$files.Values
$userinput = Read-Host -Prompt 'Please Enter Folder name to be deleted'
if ($files.ContainsKey($userinput)) {
$files[$userinput] | Remove-item
Write-Host 'Folder was deleted'
}
}
until([string]::IsNullOrWhiteSpace($userinput))
答案1
得分: 1
这是修改后的代码,我用来首先将图像文件夹移动到删除文件夹。
function Do-Menu {
[CmdletBinding()]
param (
[string]$Path = $PWD, # 默认为当前工作目录
[string]$Filter = 'Image*',
[string]$Title = '请选择要移动的文件夹'
)
cls
# 如果您只想匹配单个通配符字符串的名称,请使用 Filter,而不是 Include
$dirs = @(Get-ChildItem -Path $Path -Filter $Filter -Recurse -Directory) | Sort-Object LastWriteTime
# 仅在找到具有该名称的目录时继续
if (!$dirs.Count) {
Write-Host "没有找到与筛选器 '$Filter' 匹配的目录..."
return $false # 以 False 值退出函数
}
# 创建菜单
if (![string]::IsNullOrWhiteSpace($Title)) {
$dashLine = '-' * ($Title -split '\r?\n' | Measure-Object -Maximum -Property Length).Maximum
Write-Host "$Title`r`n$dashLine`r`n" -ForegroundColor Yellow
}
$index = 1
$dirs | ForEach-Object {
# 写出菜单项
$align = $dirs.Count.ToString().Length
# {0,$align} 将索引号对齐到右侧
# 有关更多 DateTime 格式,请参见链接
# https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings
# https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
Write-Host ("{0,$align}. {1:yyyy-MM-dd HH:mm:ss} {2}" -f $index++, $_.LastWriteTime, $_.FullName)
}
# 现在要求用户输入
$message = "`r`n请输入要删除的目录的索引号.`r`n"
if ($dirs.Count -gt 1) { $message += "要选择多个项目,请使用逗号分隔数字.`r`n" }
Write-Host $message -ForegroundColor Yellow
$selection = Read-Host
# 确保输入完全是数字,不包含 '0' 值,或高于目录数量的值
$selection = [int[]]($selection -replace '[^\d,]' -split ',' |
Where-Object { $_ -match '\d+' -and ([int]$_ -gt 0 -and [int]$_ -le $dirs.Count)})
if (!$selection.Count) { return $false } # 空输入时退出
# 遍历选定的索引并删除匹配的文件夹
$selection | ForEach-Object {
$folder = $dirs[$_ - 1]
# 确保您不试图删除刚刚删除父文件夹的文件夹
if (Test-Path -Path $folder.FullName -PathType Container) {
$folder | Move-Item -Destination $targetdir
Write-Host "文件夹 $($folder.FullName) 已被移动"
}
}
# 在短暂暂停后返回 True 以重新构建菜单
Start-Sleep 4
$true
}
# 主代码
$path = 'E:\TestEnv\Repository\images'
$targetdir = 'E:\TestEnv\deleted_images'
while ($true) {
$result = Do-Menu -Path $path
# 如果用户取消或没有与筛选器匹配的文件夹,则退出循环
if (!$result) { break }
}
cls
Write-Host "`r`n操作完成!" -ForegroundColor Green
这是修改后的代码,用于将图像文件夹移动到删除文件夹。
英文:
here is the modified code which i use to first move the image folders to the delete folder.
function Do-Menu {
[CmdletBinding()]
param (
[string]$Path = $PWD, # default to current working directory
[string]$Filter = 'Image*',
[string]$Title = 'Please select the folder(s) to move'
)
cls
# if you only want to match the name on a single wildcard string, use Filter, not Include
$dirs = @(Get-childitem -Path $Path -Filter $Filter -Recurse -Directory) | Sort-Object LastWriteTime
# only proceed if there are directories found by that name
if (!$dirs.Count) {
Write-Host "No directories found that match filter '$Filter'.."
return $false # exit the function with a value of False
}
# create the menu
if (![string]::IsNullOrWhiteSpace($Title)) {
$dashLine = '-' * ($Title -split '\r?\n' | Measure-Object -Maximum -Property Length).Maximum
Write-Host "$Title`r`n$dashLine`r`n" -ForegroundColor Yellow
}
$index = 1
$dirs | ForEach-Object {
# write out the menu items
$align = $dirs.Count.ToString().Length
# {0,$align} aligns the index number to the right
# for more DateTime formats see
# https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings
# https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
Write-Host ("{0,$align}. {1:yyyy-MM-dd HH:mm:ss} {2}" -f $index++, $_.LastWriteTime, $_.FullName)
}
# now ask for user input
$message = "`r`nType the index number of the directory you wish to delete.`r`n"
if ($dirs.Count -gt 1) { $message += "To select multiple items, separate the numbers with commas.`r`n" }
Write-Host $message -ForegroundColor Yellow
$selection = Read-Host
# make sure the input is all numeric and contains no '0' values
# or values higher than the number of directories
$selection = [int[]]($selection -replace '[^\d,]' -split ',' |
Where-Object { $_ -match '\d+' -and ([int]$_ -gt 0 -and [int]$_ -le $dirs.Count)})
if (!$selection.Count) { return $false } # exit on empty input
# loop over the selected indices and delete the matching folders
$selection | ForEach-Object {
$folder = $dirs[$_ - 1]
# make sure you are not trying to remove a folder of which the parent
# folder has just been removed
if (Test-Path -Path $folder.FullName -PathType Container) {
$folder | Move-Item -Destination $targetdir
Write-Host "Folder $($folder.FullName) has been moved"
}
}
# return True to have the menu rebuilt after a short pause
Start-Sleep 4
$true
}
# main code
$path = 'E:\TestEnv\Repository\images'
$targetdir = 'E:\TestEnv\deleted_images'
while ($true) {
$result = Do-Menu -Path $path
# if the user cancelled, or if there were no folders matching the filter, exit the while loop
if (!$result) { break }
}
cls
Write-Host "`r`nAll done!" -ForegroundColor Green
答案2
得分: 0
不要有别的内容,只返回翻译好的部分:
而不是使用 `Read-Host`(用户可以输入几乎任何内容...),我会使用 `Out-GridView`,正如 [Keith Miller](https://stackoverflow.com/questions/75953342/get-childitem-sorted-and-then-delete-upon-promt-input?noredirect=1#comment133968511_75953342) 已经建议的那样。
这将为用户提供一个图形化的目录列表,使选择一个或多个目录更容易删除。
```powershell
$path = 'E:\TestEnv\deleted_images'
# 进入一个无限循环。如果用户单击“取消”按钮或没有找到与 Filter 中的名称匹配的目录,我们将退出循环
while ($true) {
# 如果您只想匹配单个通配符字符串的名称,请使用 Filter,而不是 Include
$dirs = Get-childitem -Path $path -Filter 'Image*' -Recurse -Directory | Sort-Object LastAccessTime
# 仅在找到该名称的目录时继续
if (@($dirs).Count) {
$selection = $dirs | Out-GridView -Title '请选择要删除的文件夹' -PassThru
# 如果用户取消,退出循环
if (!$selection) { break }
# 用户可能选择了多个目录,因此使用循环
$selection | ForEach-Object {
$_ | Remove-Item -Recurse
Write-Host "文件夹 $($_.FullName) 已删除"
}
}
else {
Write-Host "未找到与筛选条件匹配的目录..."
break # 未找到该名称的目录,因此退出循环
}
}
Write-Host "全部完成" -ForegroundColor Green
根据您的评论,您无法使用图形化的 Out-GridView,以下是使用控制台菜单的方法。
function Do-Menu {
[CmdletBinding()]
param (
[string]$Path = $PWD, # 默认为当前工作目录
[string]$Filter = 'Image*',
[string]$Title = '请选择要删除的文件夹'
)
cls
# 如果您只想匹配单个通配符字符串的名称,请使用 Filter,而不是 Include
$dirs = @(Get-childitem -Path $Path -Filter $Filter -Recurse -Directory) | Sort-Object LastWriteTime
# 仅在找到该名称的目录时继续
if (!$dirs.Count) {
Write-Host "未找到与筛选条件 '$Filter' 匹配的目录..."
return $false # 返回值为 False 退出函数
}
# 创建菜单
if (![string]::IsNullOrWhiteSpace($Title)) {
$dashLine = '-' * ($Title -split '\r?\n' | Measure-Object -Maximum -Property Length).Maximum
Write-Host "$Title`r`n$dashLine`r`n" -ForegroundColor Yellow
}
$index = 1
$dirs | ForEach-Object {
# 输出菜单项
$align = $dirs.Count.ToString().Length
# {0,$align} 将索引号右对齐
# 有关更多日期时间格式,请参见链接
Write-Host ("{0,$align}. {1:yyyy-MM-dd HH:mm:ss} {2}" -f $index++, $_.LastWriteTime, $_.FullName)
}
# 现在请用户输入
$message = "`r`n请输入您要删除的目录的索引号。`r`n"
if ($dirs.Count -gt 1) { $message += "要选择多个项目,请用逗号分隔这些数字。`r`n" }
Write-Host $message -ForegroundColor Yellow
$selection = Read-Host
# 确保输入全为数字,不包含 '0' 值,且不大于目录数量
$selection = [int[]]($selection -replace '[^\d,]' -split ',' |
Where-Object { $_ -match '\d+' -and ([int]$_ -gt 0 -and [int]$_ -le $dirs.Count)})
if (!$selection.Count) { return $false } # 输入为空时退出
# 循环遍历所选的索引并删除匹配的文件夹
$selection | ForEach-Object {
$folder = $dirs[$_ - 1]
# 确保您不尝试删除刚刚删除父文件夹的文件夹
if (Test-Path -Path $folder.FullName -PathType Container) {
$folder | Remove-Item -Recurse
Write-Host "文件夹 $($folder.FullName) 已删除"
}
}
# 返回 True 以在短暂的暂停后重建菜单
Start-Sleep 4
$true
}
# 主代码
$path = 'E:\TestEnv\deleted_images'
while ($true) {
$result = Do-Menu -Path $path
# 如果用户取消,或者没有与筛选条件匹配的文件夹,退出循环
if (!$result) { break }
}
cls
Write-Host "`r`n全部完成!" -ForegroundColor Green
英文:
Instead of using Read-Host
(where a user can type in just about anything..), I would use Out-GridView
as Keith Miller already suggested.
This will provide a graphical list of directories to the user making it much easier to select one or more directories to delete.
$path = 'E:\TestEnv\deleted_images'
# enter an endless loop. We'll break out if the user clicks the Cancel button
# or when there are no directories found that match the name in the Filter
while ($true) {
# if you only want to match the name on a single wildcard string, use Filter, not Include
$dirs = Get-childitem -Path $path -Filter 'Image*' -Recurse -Directory | Sort-Object LastAccessTime
# only proceed if there are directories found by that name
if (@($dirs).Count) {
$selection = $dirs | Out-GridView -Title 'Please select the folder(s) to delete' -PassThru
# if the user cancelled, exit the while loop
if (!$selection) { break }
# the user could have selected more than one directory, so use a loop
$selection | ForEach-Object {
$_ | Remove-Item -Recurse
Write-Host "Folder $($_.FullName) has been deleted"
}
}
else {
Write-Host "No directories found that match the filter.."
break # no directory by that name found, so exit the while loop
}
}
Write-Host "All done" -ForegroundColor Green
<hr>
As per your comment you cannot use the graphical Out-GridView, here's the idea using a console menu.
function Do-Menu {
[CmdletBinding()]
param (
[string]$Path = $PWD, # default to current working directory
[string]$Filter = 'Image*',
[string]$Title = 'Please select the folder(s) to delete'
)
cls
# if you only want to match the name on a single wildcard string, use Filter, not Include
$dirs = @(Get-childitem -Path $Path -Filter $Filter -Recurse -Directory) | Sort-Object LastWriteTime
# only proceed if there are directories found by that name
if (!$dirs.Count) {
Write-Host "No directories found that match filter '$Filter'.."
return $false # exit the function with a value of False
}
# create the menu
if (![string]::IsNullOrWhiteSpace($Title)) {
$dashLine = '-' * ($Title -split '\r?\n' | Measure-Object -Maximum -Property Length).Maximum
Write-Host "$Title`r`n$dashLine`r`n" -ForegroundColor Yellow
}
$index = 1
$dirs | ForEach-Object {
# write out the menu items
$align = $dirs.Count.ToString().Length
# {0,$align} aligns the index number to the right
# for more DateTime formats see
# https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings
# https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
Write-Host ("{0,$align}. {1:yyyy-MM-dd HH:mm:ss} {2}" -f $index++, $_.LastWriteTime, $_.FullName)
}
# now ask for user input
$message = "`r`nType the index number of the directory you wish to delete.`r`n"
if ($dirs.Count -gt 1) { $message += "To select multiple items, separate the numbers with commas.`r`n" }
Write-Host $message -ForegroundColor Yellow
$selection = Read-Host
# make sure the input is all numeric and contains no '0' values
# or values higher than the number of directories
$selection = [int[]]($selection -replace '[^\d,]' -split ',' |
Where-Object { $_ -match '\d+' -and ([int]$_ -gt 0 -and [int]$_ -le $dirs.Count)})
if (!$selection.Count) { return $false } # exit on empty input
# loop over the selected indices and delete the matching folders
$selection | ForEach-Object {
$folder = $dirs[$_ - 1]
# make sure you are not trying to remove a folder of which the parent
# folder has just been removed
if (Test-Path -Path $folder.FullName -PathType Container) {
$folder | Remove-Item -Recurse
Write-Host "Folder $($folder.FullName) has been deleted"
}
}
# return True to have the menu rebuilt after a short pause
Start-Sleep 4
$true
}
# main code
$path = 'E:\TestEnv\deleted_images'
while ($true) {
$result = Do-Menu -Path $path
# if the user cancelled, or if there were no folders matching the filter, exit the while loop
if (!$result) { break }
}
cls
Write-Host "`r`nAll done!" -ForegroundColor Green
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论