Encontre e mova com excluir

2

Eu preciso usar o find e o mv juntos

requisito: precisa encontrar todos os arquivos * .xml, mas excluir deposit.xml e movê-lo para outra pasta (bastante simples)

Minha tentativa:

mv 'find ./*.xml '!' -type d | fgrep -v deposit.xml' ./Archive

Isso funciona perfeitamente se houver arquivos. Se nenhum arquivo estiver presente, será exibido abaixo do erro

mv: missing destination file operand after './Archive'
Try 'mv --help' for more information.*
    
por Peck 16.03.2015 / 17:25

4 respostas

2

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/
    
por 17.03.2015 / 02:22
1

Usando o comando "find":

find ./*.xml -type f ! -name "deposit.xml" -exec mv {} ./Archive ';'

Usando "find" com o comando "xargs":

find ./*.xml -type f ! -name "deposit.xml" | xargs -I {} mv {} ./Archive

Usando o loop "for" com o comando "find".

for f in $(find ./*.xml -type f ! -name "deposit.xml"); do mv ${f} ./Archive; done

Além disso, de acordo com a página manp para sistemas GNU / Linux , o comando "mv" tem o "- t | opção --target-directory ". Então você deve poder usá-lo com "xargs" assim:

find ./*.xml -type f ! -name "deposit.xml" | xargs mv -t ./Archive

Eu não testei isso como estou em um sistema FreeBSD.

    
por 16.03.2015 / 21:19
0

E o problema é que você não quer exibir a mensagem de erro ou que você não quer que o comando seja executado se não houver nenhum .xml?

No primeiro caso, a saída de redirecionamento 2>/dev/null e nenhuma mensagem de erro será exibida.

No segundo caso, execute

for i in $(find ./*.xml '!' -type d | fgrep -v deposit.xml);do mv $i ./Archive;done

    
por 16.03.2015 / 17:39
0
find . ! -name "deposit.xml" -name "*.xml" -exec mv {} ./temp \;

find tem a opção -exec usando o qual podemos executar comandos com o arquivo de resultado como operando e usar '! -name 'opção para excluir arquivo.

    
por 16.03.2015 / 17:50

Tags