按照排序顺序获取子项,然后根据提示输入进行删除。

huangapple go评论58阅读模式
英文:

Get-childitem sorted and then delete upon promt input

问题

以下是您要翻译的内容:

  1. "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的新手,已经尝试了几个小时,但似乎无法找到正确的组合。

  2. "this code below sorts exactly as wanted, but then delete is not working because $files is nowhere defined i think"

    下面的这段代码按照所需的方式排序,但删除操作不起作用,因为我认为$files没有被定义。

  3. "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 = &#39;Image*&#39;,
[string]$Title  = &#39;Please select the folder(s) to delete&#39;
)
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 &quot;No directories found that match filter &#39;$Filter&#39;..&quot;
return $false  # exit the function with a value of False
}
# create the menu
if (![string]::IsNullOrWhiteSpace($Title)) {
$dashLine = &#39;-&#39; * ($Title -split &#39;\r?\n&#39; | Measure-Object -Maximum -Property Length).Maximum
Write-Host &quot;$Title`r`n$dashLine`r`n&quot; -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 (&quot;{0,$align}. {1:yyyy-MM-dd HH:mm:ss}  {2}&quot; -f $index++, $_.LastWriteTime, $_.FullName)  
}
# now ask for user input
$message = &quot;`r`nType the index number of the directory you wish to delete.`r`n&quot;
if ($dirs.Count -gt 1) { $message += &quot;To select multiple items, separate the numbers with commas.`r`n&quot; }
Write-Host $message -ForegroundColor Yellow
$selection = Read-Host
# make sure the input is all numeric and contains no &#39;0&#39; values
# or values higher than the number of directories
$selection = [int[]]($selection -replace &#39;[^\d,]&#39; -split &#39;,&#39; | 
Where-Object { $_ -match &#39;\d+&#39; -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 &quot;Folder $($folder.FullName) has been deleted&quot;
}
}
# return True to have the menu rebuilt after a short pause
Start-Sleep 4
$true
}
# main code
$path = &#39;E:\TestEnv\deleted_images&#39;
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 &quot;`r`nAll done!&quot; -ForegroundColor Green

huangapple
  • 本文由 发表于 2023年4月7日 04:03:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75953342.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定