Usando arquivos que possuem espaços em seus nomes em pipes [duplicados]

4

Eu tenho a pasta chamada play , que contém um arquivo damn file (com espaço). Quando eu uso find e canalizo a saída para tar :

find play/ -name 'damn*' | tar cf archive.tar -T -

Funciona perfeitamente. Por que isso funciona A saída de find contém espaço que deve causar problemas para tar . Quando eu uso este comando:

tar cf archive.tar $(find play/ -name 'damn*')

o bash mostra esses erros:

tar: play/damn: Cannot stat: No such file or directory
tar: file: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

Estou confuso. Por que o primeiro exemplo funciona?

    
por Majid Azimi 12.02.2012 / 21:34

2 respostas

8

No segundo exemplo, as novas linhas são removidas pelo shell, que divide a palavra na saída da substituição do comando. Como novas linhas são incluídas em IFS por padrão, elas são tratadas como delimitadores de campo e não como parte dos próprios campos. No primeiro exemplo, a entrada vem de um pipe e não do shell, portanto, o shell não pode fazer a divisão de palavras.

Duplicar a substituição do comando ( "$(find ... )" ) evitará que a divisão de palavras ocorra, mas find dentro da substituição de comandos é quase sempre uma idéia ruim , então não faça isso. Para segurança máxima, sempre que você tiver acesso às versões GNU das ferramentas Unix, você deve usar as opções de delimitador nulo:

find dir/ -name '...' -print0 | tar cf foo.tar --null --no-recursion -T -
    
por 12.02.2012 / 21:50
4

find play/ -name 'damn*' produzirá uma lista de nomes de arquivos, 1 por linha. Se play/damn file for o único arquivo correspondente, será equivalente a echo 'play/damn file' .

-T option espera que os nomes dos arquivos sejam separados por novas linhas. Qualquer outro espaço em branco é considerado parte do nome do arquivo. É por isso que seu primeiro exemplo funciona.

Quando você usa $(...) , a saída do comando é dividido em espaço em branco pelo shell, e então cada palavra se torna um parâmetro para% código%. Assim, tar e play/damn se tornam dois argumentos, e nenhum deles é um arquivo existente.

    
por 12.02.2012 / 21:52