Como uso o find quando o nome do arquivo contém espaços?

16

Eu quero enviar nomes de arquivos para outros programas, mas todos eles engasgam quando os nomes contêm espaços.

Digamos que eu tenha um arquivo chamado.

foo bar

Como posso obter find para retornar o nome correto?

Obviamente, eu quero:

foo\ bar

ou:

"foo bar"

EDIT : Eu não quero passar por xargs , eu quero pegar uma string formatada corretamente de find para que eu possa canalizar a string de nomes de arquivos diretamente para outra programa.

    
por bug 01.07.2013 / 17:08

5 respostas

17

POSIXLY:

find . -type f -exec sh -c '
  for f do
    : command "$f"
  done
' sh {} +

Com find suporta -print0 e xargs suporta -0 :

find . -type f -print0 | xargs -0 <command>
A opção

-0 diz ao xargs para usar o caractere ASCII NUL em vez do espaço para finalizar (separar) os nomes dos arquivos.

Exemplo:

find . -maxdepth 1 -type f -print0 | xargs -0 ls -l
    
por 01.07.2013 / 17:18
10

Usar -print0 é uma opção, mas nem todos os programas suportam o uso de fluxos de dados delimitados por nullbyte, portanto, você precisará usar xargs com a opção -0 para algumas coisas, como a resposta do Gnouc observou.

Uma alternativa seria usar as opções find -exec ou -execdir . O primeiro dos seguintes itens alimentará os nomes de arquivos para somecommand , um de cada vez, enquanto o segundo será expandido para uma lista de arquivos:

find . -type f -exec somecommand '{}' \;
find . -type f -exec somecommand '{}' +

Você pode achar que é melhor usar globbing em muitos casos. Se você tiver um shell moderno (bash 4+, zsh, ksh), poderá obter globalização recursiva com globstar ( ** ). No bash, você precisa definir isso:

shopt -s globstar
somecommand ./**/*.txt ## feeds all *.txt files to somecommand, recursively

Eu tenho uma linha dizendo shopt -s globstar extglob no meu .bashrc, então isso está sempre habilitado para mim (assim como os globs estendidos, que também são úteis).

Se você não quiser recursividade, obviamente use apenas ./*.txt , para usar todos os * .txt no diretório de trabalho. O find tem alguns recursos de pesquisa refinados muito úteis e é obrigatório para dezenas de milhares de arquivos (nesse ponto você encontrará o número máximo de argumentos do shell), mas para o uso diário é desnecessário.

    
por 01.07.2013 / 18:11
3

Pessoalmente, eu usaria a ação -exec find para resolver esse tipo de problema. Ou, se necessário, xargs , que permite a execução paralela.

No entanto, existe uma maneira de obter find para produzir uma lista legível de nomes de arquivos. Não é novidade que use -exec e bash , em particular uma extensão para o comando printf :

find ... -exec bash -c 'printf "%q " "$@"' printf {} ';'

No entanto, enquanto isso imprimirá corretamente as palavras com escape de shell, não será utilizável com $(...) , porque $(...) não interpreta aspas ou escapa. (O resultado de $(...) está sujeito à divisão de palavras e à expansão do nome do caminho, a menos que esteja entre aspas.) Assim, o seguinte não fará o que você deseja:

ls $(find ... -exec bash -c 'printf "%q " "$@"' printf {} +)

O que você precisa fazer é:

eval "ls $(find ... -exec bash -c 'printf "%q " "$@"' printf {} +)"

(Note que eu não fiz nenhuma tentativa real de testar a monstruosidade acima.)

Mas você também pode:

find ... -exec ls {} +
    
por 01.07.2013 / 22:00
0
find ./  | grep " "

irá fazer com que os arquivos e diretórios contenham espaços

find ./ -type f  | grep " " 

irá fazer com que os arquivos contenham espaços

find ./ -type d | grep " "

vai te dar os diretórios contém espaços

    
por 06.05.2016 / 17:59
-2
    find . -type f -name \*\  | sed -e 's/ /<thisisspace>/g'
    
por 02.04.2018 / 17:18

Tags