Primeiro, por que sua tentativa não funciona: -printf "%h\n"
imprime a parte do diretório do nome do arquivo .avi
. Isso não afeta nada na ação -exec
subseqüente - {}
não significa “seja qual for o último comando printf
impresso”, significa “o caminho para o arquivo encontrado”.
Se você quiser usar a parte do diretório do nome do arquivo nesse comando cp
, precisará modificar o nome do arquivo antes de passá-lo para cp
. O comando find
não tem esse recurso, mas um shell faz isso, portanto, faça find
invocar um shell que chama cp
.
find . -name "*.avi" -exec sh -c 'cp -Rp "${0%/*}" /share/USBDisk1/Movies/' {} \;
Você precisará passar -r
para cp
, já que está copiando um diretório. Você provavelmente deve preservar os metadados, como o tempo de modificação dos arquivos, também, com -p
.
Você pode substituir cp -Rp
por rsync -a
. Dessa forma, se você já copiou um diretório de filmes, ele não será copiado novamente (a menos que seu conteúdo tenha sido alterado).
Seu comando tem um defeito que pode ou não afetar você: se um diretório contiver vários arquivos .avi
, ele será copiado várias vezes. Seria melhor procurar diretórios e copiá-los se eles contiverem um arquivo .avi
, em vez de procurar .avi
files. Se você usar rsync
em vez de cp
, os arquivos não serão copiados novamente, é só um pouco mais de trabalho para rsync
verificar a existência dos arquivos repetidamente.
Se todos os diretórios de filme estiverem imediatamente abaixo do diretório de nível superior, você não precisará de find
, um loop simples sobre um padrão curinga é suficiente.
for d in ./*/; do
set -- "$d/"*.avi
if [ -e "$1" ]; then
# there is at least one .avi file in $d
cp -rp -- "$d" /share/USBDisk1/Movies/
fi
done
Se os diretórios de filmes podem ser aninhados (por exemplo, Movies/science fiction/Ridley Scott/Blade Runner
), você não precisa de find
, um loop simples sobre um padrão de caractere curinga é suficiente. Você precisa estar executando ksh93 ou bash ≥4 ou zsh, e no ksh93 você precisa executar set -o globstar
primeiro, e no bash você precisa executar shopt -s globstar
primeiro. O padrão curinga **/
corresponde ao diretório atual e a todos os seus subdiretórios recursivamente (o bash também percorre links simbólicos para subdiretórios).
for d in ./**/; do
set -- "$d/"*.avi
if [ -e "$1" ]; then
cp -rp -- "$d" /share/USBDisk1/Movies/
fi
done