Windows - 根据其他文件的存在来复制文件

Windows - 根据其他文件的存在来复制文件

我有一个文件夹,里面有 jpg 格式的照片子文件夹。文件排列如下:

Z:\jpgs\Armouries\fb\IMG_1286.jpg
Z:\jpgs\Balloon\fb\IMG_1129.jpg
Z:\jpgs\Party\fb\P5060092.jpg

等等...这样的有几百个。

我还有另一个文件夹,其中包含以下子文件夹:

z:\masters\Armouries\IMG_1286.RAW
z:\masters\Balloon\IMG_1129.DNG
z:\masters\Party\P5060092.CR2

等等... 又有数百个这样的文件夹。

我想要做的是,仅当“jpgs”树中存在相同文件名时,才将“masters”树中的文件复制到新文件夹。 masters 树中的所有文件并非都有相应的 jpg - 这些文件将被忽略。

希望我已经解释清楚了...有什么指点吗?

答案1

$jpgs = "C:\jpgs"
$masters = "C:\masters"
$destination = "C:\new"

# store all BaseNames and necessary parent folders to match in an array
$namesToMatch = @()
gci $jpgs -File -Recurse | select -ExpandProperty FullName -Uniq | % {
    # BaseName and parent folder(s) (eg "\Armouries\IMG_1286")
    $namesToMatch += (($_ -split "\\jpgs")[-1] -split "\.")[0]
}

# evaluate each file we might need to copy
gci $masters -File -Recurse | select -ExpandProperty FullName -Uniq | % {

    # BaseName and parent folder(s) (eg "\Armouries\IMG_1286")
    $name = (($_ -split "\\masters")[-1] -split "\.")[0]
    # path + Fullname, in the "new" folder structure (eg "C:\new\Armouries\IMG_1286.jpg")
    $desiredDestination = $_ -replace "masters","new"
    # path in the "new" folder structure with no file name (eg "C:\new\Armouries")
    $desiredDestination_noFile = $desiredDestination.Substring(0,$desiredDestination.LastIndexOf("\"))

    # if we should copy this file
    if($name -in $namesToMatch) {

        # create the parent directories if needed
        if(!(Test-Path -Path $desiredDestination_noFile)) {
            md -force $desiredDestination_noFile | Out-File null
        }

        # copy the file
        cp $_ $desiredDestination

    }
}

答案2

此答案假设与问题中的约定相同,即母版在 中z:\masters,JPG 在 中z:\jpgs。目标文件夹假定为z:\dest

简短回答

dir -File -Recurse z:\masters\ | % { if (dir -Recurse  "z:\jpgs\$($_.BaseName).jpg") { mkdir -ErrorAction SilentlyContinue $($_.Directory -replace "\\masters\\", "\dest\"); cp $_.FullName $($_.FullName -replace "\\masters\\", "\dest\")} }

简要说明:对于z:\masters其直接或间接子目录中的每个文件或其直接或间接子目录之一,它会检查任何直接或间接子目录是否z:\jpgs包含具有相同基本名称的 JPG 文件,如果是,则在必要时创建父目录后将主文件复制到目标文件夹。

您可以测试此解决方案在线。(注:在线版本使用/而不是 作为路径分隔符,\因为它运行在 Linux 上,而New-Item -Type Directory而不是mkdir由于在线执行环境的限制。)

使用适当的缩进和扩展别名

Get-ChildItem -File -Recurse z:\masters\ | ForEach-Object {
    if (Get-ChildItem -Recurse  "z:\jpgs\$($_.BaseName).jpg") {
        mkdir -ErrorAction SilentlyContinue $($_.Directory -replace "\\masters\\", "\dest\")
        Copy-Item $_.FullName $($_.FullName -replace "\\masters\\", "\dest\")
    }
}

详细说明

  • dir -File -Recurse z:\masters\列出z:\masters及其子目录中的所有文件 ( -Recurse)。dir获取子项
  • %ForEach 对象{}. 它为管道中的每个对象执行一个脚本块(用括号括起来)。
  • $_是个管道中的当前对象(即主文件之一)。
  • dir -Recurse "z:\jpgs\$($_.BaseName).jpg"返回z:\jpgs目录及其子目录中所有与当前主文件具有相同基本名称 ( $_.BaseName) 和扩展名的文件。如果没有,则.jpg返回,然后在评估语句的条件时将其转换为。$null$falseif
  • $_.FullName -replace "\\masters\\", "\dest\"是目标文件的完整路径:它是主文件的完整路径($_.FullName),\masters\其中\dest\使用-replace 运算符。这用于具有与 中相同的目录\dest结构\masters
  • mkdir -ErrorAction SilentlyContinue $($_.Directory -replace "\\masters\\", "\dest\")创建目标文件的父文件夹。此步骤是必需的,因为 Copy-Item目前不允许(自 PowerShell 6.1 起)在必要时创建父目录,如果父目录缺失,则命令会失败。如果父目录已存在,则该-ErrorAction SilentlyContinue参数可防止mkdir命令失败。
  • Copy-Item $_.FullName $($_.FullName -replace "\\masters\\", "\dest\")将主文件复制到目标文件夹。

评论

$_.FullName -replace "\\masters\\", "\dest\"表达式中,\第一个参数中的反斜杠 ( ) 是双倍的,-replace但第二个参数中的反斜杠不是双倍的。这是因为-replace 运算符正则表达式其中反斜杠是需要转义的特殊字符,而反斜杠不是替换字符串(第二个参数)中的特殊字符。

相关内容