powershell 使用Get-ChildItem排除文件夹-需要帮助调试脚本

ao218c7q  于 2023-03-08  发布在  Shell
关注(0)|答案(2)|浏览(183)

我已经搜索了StackOverflow和SuperUser来尝试解决这个问题,但我仍然被一个我不知道如何解决的问题所困扰。我知道这很简单,但在玩了一个小时之后,我仍然被难倒了。简单的问题:我该怎么告诉Get-Childitem排除文件夹呢?
最前面的代码是不起作用的:

$sourceDir="E:\Deep Storage"
$targetDir="W:\Deep Storage"
$excludeThese = 'Projects2','Projects3','Projects4';

Get-ChildItem -Path $sourceDir -Directory -Recurse | 
  where {$_.fullname -notin $excludeThese} |
    Get-ChildItem -Path $sourceDir | ForEach-Object {
        $num=1
        $nextName = Join-Path -Path $targetDir -ChildPath $_.name
    
        while(Test-Path -Path $nextName)
        {
           $nextName = Join-Path $targetDir ($_.BaseName + "_$num" + $_.Extension)    
           $num+=1   
        }

        $_ | Move-Item -Destination $nextName -Force -Verbose -WhatIf
    }
}

这里的基本概念已经奏效:

$sourceDir="E:\Deep Storage"
$targetDir="W:\Deep Storage"

Get-ChildItem -Path $sourceDir -File -Recurse | ForEach-Object {
    $num=1
    $nextName = Join-Path -Path $targetDir -ChildPath $_.name

    while(Test-Path -Path $nextName)
    {
       $nextName = Join-Path $targetDir ($_.BaseName + "_$num" + $_.Extension)    
       $num+=1   
    }

    $_ | Copy-Item -Destination $nextName -Verbose
}

基本上,它的作用是将文件夹从一个位置移动到另一个位置,如果文件在两个位置都存在,它会重命名传入的文件。它有助于保持我的存档驱动器清晰。但有三个文件夹我想排除,因为我仍然定期从它们中提取资产,所以我不需要移动这些文件。
因此,两个代码样本之间存在差异:在第一个示例中,我试图让Get-Childitem排除特定的三个文件夹,而第二个示例只是一次获取所有内容。
我试着用$excludeThese作为变量直接执行排除,但没有成功;我试着完全跳过变量方法,只在-Exclude之后输入文件夹名称,但仍然不起作用。我还试着输入我想排除的文件夹的完整路径。没有用--无论我做什么,-WhatIf显示脚本试图移动所有内容,包括我理论上排除的文件夹。
我尝试的最后一个技巧是我在SO上遇到的,那就是先对exclude参数进行gci,然后再做一个gci,但还是失败了,所以现在我不得不向Maven寻求帮助。

yhuiod9q

yhuiod9q1#

我会使用一个正则表达式字符串从(转义)目录名创建排除,以确保这些文件夹内的文件被忽略。
此外,通过使用目标文件夹中已经存在的所有文件名的查找Hashtable,确定具有特定名称的文件是否已经存在是非常快的。

$sourceDir    = 'E:\Deep Storage'
$targetDir    = 'W:\Deep Storage'
$excludeThese = 'Projects2','Projects3','Projects4';

# create a regex string with all folder names to exclude combined with regex OR (|)
$excludeDirs = ($excludeThese | ForEach-Object { [Regex]::Escape($_) }) -join '|'
# create a lookup Hashtable and store the filenames already present in the destination folder
$existingFiles = @{}
Get-ChildItem -Path $targetDir -File | ForEach-Object { $existingFiles[$_.Name] = $true }

Get-ChildItem -Path $sourceDir -File -Recurse | 
Where-Object {$_.DirectoryName -notmatch $excludeDirs} |
ForEach-Object {
    # construct the new filename by appending an index number if need be
    $newName = $_.Name
    $count   = 1
    while ($existingFiles.ContainsKey($newName)) {
        $newName = "{0}_{1}{2}" -f $_.BaseName, $count++, $_.Extension
    }
    # add this new name to the Hashtable so it exists in the next run
    $existingFiles[$newName] = $true
    # use Join-Path to create a FullName for the file
    $newFile = Join-Path -Path $targetDir -ChildPath $newName
    $_ | Move-Item -Destination $newFile -Force -Verbose -WhatIf
}
dgiusagp

dgiusagp2#

假设排除的目录位于顶部:

$sourceDir="E:\Deep Storage"
$excludeThese = 'Projects2','Projects3','Projects4'
get-childitem $sourcedir -exclude $excludethese | get-childitem -recurse

相关问题