Этот ответ предполагает те же соглашения, что и в вопросе, то есть мастера находятся в 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 это псевдоним для Get-ChildItem
% является псевдонимом ForEach-Object. Он выполняет блок скрипта (заключенный в фигурные скобки {}) для каждого объекта в конвейере.
$_ - текущий объект в конвейере (т. е. один из основных файлов).
dir -Recurse "z:\jpgs\$($_.BaseName).jpg" возвращает все файлы в каталоге z:\jpgs и его подкаталогах с базовым именем, совпадающим с текущим основным файлом ($_.BaseName) и расширение .jpg . Он возвращает $null если его нет, который затем преобразуется в $false когда он оценивается как условие оператора if .
$_.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 является регулярным выражением, в котором обратная косая черта - это специальный символ, который необходимо экранировать, тогда как обратная косая черта не является специальным символом в строке замены (второй параметр).