Como construir caminhos completos separados por espaços de arquivos recursivamente correspondentes glob?

4

Eu tenho um programa que requer caminhos para arquivos como argumentos, que não podem ser citados e não devem depender do diretório de trabalho. Isso pode ser feito sem encadear vários xargs , tr , find , readlink s?

Exemplo de saída para arquivos "* .csv": /home/user/a\ b.csv /home/user/my\ dir/c\ d\.csv

    
por sevo 22.07.2014 / 11:11

2 respostas

4

Para passar caminhos de arquivo como argumentos para um comando, find faz isso em seu possui sua -exec opção sem nenhum truque xargs :

find /home/user -name '*.csv' -exec yourcommand '{}' +

Isso localizará todos os arquivos chamados *.csv in /home/user e, em seguida, executará yourcommand /home/user/a\ b.csv /home/user/my\ dir/c\ d\.csv ... com todos os arquivos encontrados como argumentos. Cada arquivo encontrado é passado como um argumento completo separado para o programa, portanto, não há escape ou qualquer outra coisa necessária: yourcommand obtém muitos argumentos, que são exatamente o caminho completo do arquivo.

Outra abordagem é que alguns shells ( zsh em particular ) suportam globbing mais avançado, onde você poderia apenas escreva:

yourcommand **/*.csv

e obtenha exatamente o efeito acima também.

Se você realmente quer as próprias seqüências de caracteres escapadas , ao invés de executar um comando diretamente, você pode usar bash 's built-in printf :

find /home/user -name '*.csv' -exec bash -c 'printf "%q " "$@"' dummy '{}' +

A especificação do formato %q se expande para uma versão do argumento de seqüência de caracteres com escape do shell. Com muitos argumentos, printf repete a cadeia de formatos para todos eles, portanto, isso produz sequências de escape com exceção de espaço de todos os argumentos para o comando bash -c . dummy é usado como o valor de $0 e "$@" fornece printf todos os demais argumentos, que são seus nomes de arquivo (intactos). Para o seu exemplo, isso produziria exatamente /home/user/a\ b.csv /home/user/my\ dir/c\ d\.csv .

    
por 22.07.2014 / 11:27
2

com zsh :

print -r -- **/*.csv(D:a:q)

Observe que alguns caracteres (como newline, tab ou não imprimíveis) são renderizados com a notação $'...' , o que pode ser um problema para você.

Outra abordagem é:

print -r -- *.csv(e/'REPLY=${(qq)REPLY:a}'/)

Onde todos os caminhos de arquivo estão entre aspas simples.

    
por 22.07.2014 / 13:17