find -exec mv pára após o primeiro exec

6

Enquanto pesquisava sobre essa questão: Find e mover diretórios com base no tipo de arquivo e na data , me deparei com um problema meu.

Primeiro, criei vários diretórios com arquivos neles:

seq 10 | while read dir; do
  mkdir dir$dir
  touch dir$dir/file.txt
  seq 5 | while read file; do
    touch dir$dir/file${dir}_$file
  done
done

Então tentei seguir o comando find:

$ find -type f -name "*.txt"
./dir6/file.txt
./dir8/file.txt
./dir10/file.txt
...

Funciona como esperado.

Agora com um -exec :

$ find -type f -name "*.txt" -exec sh -c 'echo mv -v "${0%/*}" ../bar' {} \;
mv -v ./dir6 ../bar
mv -v ./dir8 ../bar
mv -v ./dir10 ../bar
...

Funciona como esperado.

Agora o comando real:

$ find -type f -name "*.txt" -exec sh -c 'mv -v "${0%/*}" ../bar' {} \;
'./dir6' -> '../bar/dir6'

Ele pára após o primeiro mv . Nenhuma mensagem de erro. O status de saída é 0. O diretório bar existe e dir6 é movido corretamente.

Quando eu executo novamente, isso acontece:

$ find -type f -name "*.txt" -exec sh -c 'mv -v "${0%/*}" ../bar' {} \;
'./dir8' -> '../bar/dir8'

Pare novamente após o primeiro mv . O status de saída é 0. dir8 é movido corretamente.

Por que find é interrompido após o primeiro mv ? Porque o diretório foi movido e find está confuso? Por que não imprime um erro ou retorna um status de saída de erro?

Quando eu crio mais diretórios e mais arquivos, ele tem o mesmo comportamento.

Na questão vinculada acima, o problema é que find é executado uma vez sem problema, mas imprime erros para todas as correspondências depois disso. Isso está relacionado?

Usando find (GNU findutils) 4.4.2 .

    
por lesmana 21.08.2013 / 20:44

1 resposta

5

Em:

find -type f -name "*.txt" -exec sh -c 'mv -v "${0%/*}" ../bar' {} \;

find abre o diretório atual ( . ), obtém o conteúdo ( list1 ). Em seguida, passa a processar essa lista. Ele processa dir6 ; como esse arquivo é um diretório, ele entra nele, abre, obtém uma segunda lista de arquivos ( list2 ), processa file.txt e faz:

mv -v ./dir6 ../bar

Agora, o diretório atual de find não foi alterado, mas seu caminho foi alterado: agora é ../bar/dir6 . Depois de terminar de percorrer o conteúdo de dir6 , ele volta para cima ( chdir("..") ) e agora está em ../bar . find detecta que o diretório não é o mesmo que antes e sai .

    
por 21.08.2013 / 21:08

Tags