Mover arquivos com find + xargs: target não é um diretório?

9

Quando executo o seguinte comando:

> mkdir some_dir
> find /foo/bar/ -name '*.csv' -print0 | xargs -0 mv {} some_dir

Eu recebo centenas de linhas que dizem:

mv: target `/foo/bar/XX.csv` is not a directory

Por quê? Eu pensei que xargs iria executar:

mv /foo/barXX.csv some_dir

para cada arquivo que findencontrar. O que está acontecendo? By the way, isso é com zsh

Atualizar:

Update1:

Eu tentei:

find /foo/bar/ -name '*.csv' -print0 | xargs -0 mv {} -t some_dir

mas então eu tenho algumas linhas como:

mv: cannot stat `{}': No such file or directory

embora eu ache que o comando esteja movendo meus arquivos corretamente.

Update2:

Parece que não preciso da -topção ao usar mvsozinho. Por exemplo

> touch file1.txt
> touch file2.txt
> mkdir my_dir
> mv  file1.txt  file2.txt  my_dir

funciona bem. Por que eu preciso -tao usar xargs?

Amelio Vazquez-Reina
fonte

Respostas:

14

Supondo que você tenha GNU ( find, xargs, e mv), altere seu comando para isso:

$ find /foot/bar/ -name '*.csv' -print0 | xargs -0 mv -t some_dir

trecho da mvpágina de manual

   -t, --target-directory=DIRECTORY
          move all SOURCE arguments into DIRECTORY

O acima xargs ...irá construir o comando para que as chamadas para mover sejam assim:

 $ mv 1.csv 2.csv 3.csv ... -t some_dir

Não precisa de xargs

Você pode pular essa abordagem apenas fazendo findtodo o trabalho:

$ find /foot/bar/ -name '*.csv' -exec mv -t some_dir {} +

Por que você precisa do mv -t ...?

Isso tem a ver com a maneira como xargsestá construindo o conjunto de arquivos a serem passados ​​para o comando que será executado a cada vez (ie mv ...).

Ao executar o mvcomando manualmente, você controla quantos nomes de arquivos são passados ​​para ele e, portanto, não precisa se preocupar com a necessidade, -t my_dirpois sempre colocará o diretório de destino por último.

Referências

slm
fonte
Obrigado! Isso é muito útil. Estou um pouco confuso embora (ver minhas atualizações)
Amelio Vazquez-Reina
1
O comando construído é mv -t some_dir 1.csv 2.csv 3.csv ...para que os argumentos do arquivo sejam os últimos. Esse é o erro na pergunta, a fim de usar {}você tem que passar -I {}para xargs.
frostschutz
Obrigado. Isso explica tudo. E a segunda pergunta que tive na atualização 2? Você sabe por que eu não preciso de -tvários arquivos e um diretório com um arquivo regular mv?
Amelio Vazquez-Reina
1
@ user815423426 - Vou atualizá-lo mais tarde quando tiver uma chance hoje à noite, sei por quê.
slm
@ user815423426 - Atualizei a pergunta, deixe-me saber se faz sentido mv -t.
Slm
1

Você também pode usar o comando ls em vez do comando find:

ls /foot/bar/*.csv | xargs  mv -t some_dir
Luis Ángel Rodríguez
fonte