Geralmente, é uma má ideia analisar a saída de ls
ou find
, porque não é possível distinguir quais caracteres fazem parte de um nome de arquivo e quais caracteres são separadores. Se você não controlar os nomes dos arquivos, isso pode ser uma falha de segurança, permitindo que um adversário crie nomes de arquivos que façam com que seu script execute código arbitrário. Veja Por que meu script de shell engasgar com espaço em branco ou outros caracteres especiais? . Pode ser ok no seu caso, especialmente porque seus arquivos parecem ser algum tipo de árvore de código-fonte onde é comum ter nomes de arquivos sem caracteres “exóticos”, em particular sem espaços.
Ainda assim, não é realmente mais difícil usar um comando robusto. A ideia principal é tornar find
invocar mv
em vez de analisar a saída de find
. O comando a seguir move .xml
do diretório atual e dos subdiretórios recursivamente:
find . ! -type d -name '*.xml' ! -name deposit.xml -exec mv {} ./Archive \;
Para acelerar um pouco, você pode agrupar invocações de mv
executando um shell intermediário.
find . ! -type d -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +
Se você pretendia mover apenas arquivos do diretório atual, sem precisar de subdiretórios, precisa instruir find
a não reciclar. Se a sua implementação find
suportar a opção -maxdepth
:
find . -maxdepth 1 ! -type d -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +
Caso contrário:
find . -name . -o -type d -prune -o -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +
Se o seu shell é ksh, você pode usar seus globs estendidos. Isso é mais fácil do que usar find
, mas menos portável. Para mover arquivos no diretório atual:
mv !(deposit).xml Archive/
No ksh93, para mover arquivos de subdiretórios também:
set -o globstar
mv **/!(deposit).xml Archive/
No bash, você também pode usar o padrão !(…)
, mas precisa executar shopt -s extglob
primeiro. Para usar o padrão **/
, você precisa executar shopt -s globstar
primeiro e tenha cuidado com o bash 4.2, **/
percorre links simbólicos para diretórios e diretórios.
shopt -s extglob globstar
mv **/!(deposit).xml Archive/
No zsh, você pode usar o padrão !(…)
depois de executar setopt ksh_glob
. Como alternativa, você pode usar a sintaxe do zsh para isso depois de executar setopt extended_glob
. A sintaxe de passagem recursiva está disponível nos dois sentidos.
setopt extglob
mv **/(^deposit).xml Archive/