Essa resposta assume as mesmas convenções da pergunta, ou seja, os mestres estão em z:\masters e os JPGs estão em z:\jpgs . A pasta de destino é assumida como z:\dest .
Resposta curta
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\")} }
Breve explicação: para cada arquivo em z:\masters ou um de seus subdiretórios diretos e indiretos, ele verifica se algum subdiretório direto ou indireto de z:\jpgs contém um arquivo JPG com o mesmo nome base e, em caso afirmativo, copia o mestre arquivo para a pasta de destino depois de criar os diretórios pai, se necessário.
Você pode testar esta solução on-line . (Nota: a versão online usa / como o separador de caminho em vez de \ porque é executado no Linux e New-Item -Type Directory em vez de mkdir devido a uma limitação do ambiente de execução on-line.)
Com recuo e aliases adequados expandidos
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\")
}
}
Explicação detalhada
-
dir -File -Recurse z:\masters\ lista todos os arquivos em z:\masters e seus subdiretórios ( -Recurse ). dir é um alias para Get-ChildItem
-
% é um alias para ForEach-Object . Ele executa um bloco de script (entre chaves {} ) para cada objeto no pipeline.
-
$_ é o objeto atual no pipeline (ou seja, um dos arquivos principais).
-
dir -Recurse "z:\jpgs\$($_.BaseName).jpg" retorna todos os arquivos no diretório z:\jpgs e seus subdiretórios que possuem o mesmo nome base do arquivo mestre atual ( $_.BaseName ) e uma extensão .jpg . Ele retorna $null se não houver nenhum, que é então convertido para $false quando é avaliado como a condição da instrução if .
-
$_.FullName -replace "\masters\", "\dest\" é o caminho completo do arquivo de destino: é o caminho completo do arquivo mestre ( $_.FullName ), em que \masters\ é substituído por \dest\ usando os -replace operator . Isso é usado para ter a mesma estrutura de diretório em \dest como em \masters .
-
mkdir -ErrorAction SilentlyContinue $($_.Directory -replace "\masters\", "\dest\") cria as pastas pai do arquivo de destino. Esta etapa é necessária porque o Copy-Item atualmente não permite (a partir do PowerShell 6.1) criar diretórios pai, se necessário, e falhar quando eles estiverem ausentes. O parâmetro -ErrorAction SilentlyContinue impede que o comando mkdir falhe se os diretórios pai já existirem.
-
Copy-Item $_.FullName $($_.FullName -replace "\masters\", "\dest\") copia o arquivo mestre para a pasta de destino.
Observações
Na expressão $_.FullName -replace "\masters\", "\dest\" , barras invertidas ( \ ) são duplicadas no primeiro parâmetro para -replace , mas não no segundo. Isso ocorre porque o primeiro parâmetro para o operador de substituição é uma expressão regular na qual uma folga é um caractere especial que precisa ser escapado, enquanto que a barra invertida não é um caractere especial na sequência de substituição (o segundo parâmetro).