rsync
tem um sinalizador, --existing
, que evitará a cópia de arquivos que ainda não existem no destino:
find . -type f -name '*.txt' -exec rsync --existing {} "$HOME/alltxt/" ';'
Também adicionei -type f
para garantir que find
encontre apenas arquivos regulares e removi o -R
flag ( --relative
) de rsync
porque não acho que é útil nesse caso (usar esse sinalizador também é a razão pela qual você obtém os subdiretórios no destino). Eu também estou usando $HOME
ao invés de ~
porque eu acho que parece mais legal.
Você também pode adicionar -a
( --archive
) à invocação rsync
para preservar os tempos de propriedade e modificação, etc.
Uma abordagem semelhante, mas usando cp
em vez de rsync
:
find . -type f -name '*.txt' \
-exec sh -c 'for n; do d="$HOME/alltxt/${n##*/}"; [ -f "$d" ] && cp "$n" "$d"; done' sh {} +
Isso encontra todos os arquivos .txt
e chama um script de shell curto:
for n; do
d="$HOME/alltxt/${n##*/}"
[ -f "$d" ] && cp "$n" "$d"
done
Esse loop recebe vários arquivos .txt
de find
. Para cada um desses nomes n
, ele cria o caminho do arquivo de destino em d
, verifica se o caminho se refere a um arquivo regular existente e, em caso afirmativo, copia o arquivo fornecido para lá.
Em vez do teste [ -f "$d" ]
, você pode usar [ "$d" -ot "$n" ]
, o que será verdadeiro se o arquivo de destino existir e for mais antigo que o arquivo encontrado. Este é um teste fora do padrão, mas é suportado pela maioria dos shells.
A substituição de variável ${n##*/}
removerá os diretórios do caminho em n
, de modo que ./some/path/file.txt
seja transformado em apenas file.txt
(o nome base). Pode ser substituído por $(basename "$n")
.