Copie todos os arquivos com uma determinada extensão de todos os subdiretórios

111

No unix, desejo copiar todos os arquivos com uma determinada extensão (todos os arquivos do Excel) de todos os subdiretórios para outro diretório. Eu tenho o seguinte comando:

cp --parents `find -name \*.xls*` /target_directory/

Os problemas com este comando são:

  • Ele copia a estrutura do diretório também, e eu só quero os arquivos (então todos os arquivos devem terminar em / target_directory /)

  • Ele não copia arquivos com espaços nos nomes dos arquivos (que são alguns)

Alguma solução para esses problemas?

Abdel
fonte
Sobre o quê find... exec mv?
fedorqui 'ASSIM, pare de prejudicar'

Respostas:

173

--parents está copiando a estrutura de diretório, então você deve se livrar disso.

A maneira como você escreveu isso é findexecutado e a saída é colocada na linha de comando de forma que cpnão possa distinguir entre os espaços que separam os nomes dos arquivos e os espaços dentro do nome do arquivo. É melhor fazer algo como

$ find . -name \*.xls -exec cp {} newDir \;

no qual cpé executado para cada nome de arquivo que findencontra e passa o nome do arquivo corretamente. Aqui estão mais informações sobre essa técnica.

Em vez de tudo acima, você pode usar zsh e simplesmente digitar

$ cp **/*.xls target_directory

zsh pode expandir curingas para incluir subdiretórios e torna esse tipo de coisa muito fácil.

Brian Agnew
fonte
2
Sim. 'bin it' significa jogá-lo fora. Agora alterado :-)
Brian Agnew
13
Bash4.0+ e ksh93também suporta **. Para bash, use shopt -s globstarpara habilitá-lo. Para ksh, é set -Gou set -o globstar.
pynexj
2
@Daryl - Eu preenchi mais detalhes. Mas a resposta já estava marcada como 'aceita', nota
Brian Agnew
5
Esse executivo é tecnicamente menos eficiente do que passar para xargs, que fará tudo com o find . -name '*.xls' -print0 | xargs -0 cp -t destdir
menor número
2
@BrianAgnew Oh, tenho certeza, é bom ter informações extras nos comentários para googlers rebeldes.
Taywee 01 de
37

De todos os itens acima, eu vim com esta versão. Esta versão também funciona para mim no terminal de recuperação do mac.

find ./ -name '*.xsl' -exec cp -prv '{}' '/path/to/targetDir/' ';'

Ele irá procurar no diretório atual e recursivamente em todos os subdiretórios por arquivos com a extensão xsl. Ele os copiará todos para o diretório de destino.

Os sinalizadores cp são:

  • p - preserva atributos do arquivo
  • r - recursivo
  • v - detalhado (mostra o que está sendo copiado)
guya
fonte
1
Isso é o mesmo que eu tive que fazer quando fiz SSH em Bluehost.
Plummer
4
Ele NÃO preserva subdiretórios.
b005t3r
3
@ b005t3r é por design, não deveria. Essa era toda a intenção da pergunta do OP. Ele queria que todos os arquivos de subdiretórios fossem copiados para um diretório sem subdiretórios
Madivad
2
Existe uma maneira de modificar isso para preservar os subdiretórios?
Matthew Dean
8

Eu tive um problema parecido. Eu resolvi usando:

find dir_name '*.mp3' -exec cp -vuni '{}' "../dest_dir" ";"

O '{}'e ";"executa a cópia em cada arquivo.

StingMantis
fonte
3

Eu também tive que fazer isso sozinho. Fiz isso por meio do argumento --parents para cp:

find SOURCEPATH -name filename*.txt -exec cp --parents {} DESTPATH \;
Aquele cara
fonte
1
find [SOURCEPATH] -type f -name '[PATTERN]' | 
    while read P; do cp --parents "$P" [DEST]; done

você pode remover o --parents, mas existe o risco de colisão se vários arquivos tiverem o mesmo nome.

Camion
fonte