A iteração recursiva dos arquivos em um diretório pode ser facilmente realizada por:
find . -type f -exec bar {} \;
No entanto, o acima exposto não funciona para coisas mais complexas, onde muitas ramificações condicionais, repetições etc. precisam ser feitas. Eu costumava usar isso para o acima:
while read line; do [...]; done < <(find . -type f)
No entanto, parece que isso não funciona para arquivos que contêm caracteres obscuros:
$ touch $'a\nb'
$ find . -type f
./a?b
Existe uma alternativa que lida bem com caracteres tão obscuros?
find ... -exec bash -c 'echo filename is in \$0: "$0"' {} \;
é a melhor maneira de fazer isso.read line
paraIFS= read -r line
. O único caractere que o quebrará é uma nova linha.-d $'\0'
é preferível.Respostas:
Mais um uso seguro
find
:(Isso funciona com qualquer POSIX
find
, mas a parte do shell requer bash. Com * BSD e GNU find, você pode usar em-print0
vez de-exec printf '%s\0' {} +
, será um pouco mais rápido.)Isso torna possível usar a entrada padrão dentro do loop e funciona com qualquer caminho.
fonte
do echo "Filename is '$REPLY'"
Fazer isso é tão simples quanto:
Ou...
fonte
A abordagem mais simples (ainda que segura) é usar globbing de shell:
Para fazer a recursão acima em subdiretórios (no bash), você pode usar a
globstar
opção; também definidodotglob
para corresponder aos arquivos cujo nome começa com.
:Cuidado com o fato de que, até o bash 4.2, se
**/
repete em links simbólicos para diretórios. Desde o bash 4.3, ele se**/
repete apenas em diretórios, comofind
.Outra solução comum é usar
find -print0
comxargs -0
:Observe que
h:/g
está realmente correto, pois o nome do arquivo contém a\r
.fonte
É um pouco difícil de fazer seu loop de leitura portably, mas para a festança, em particular, você pode tentar algo como isso .
Parte relevante:
Isso instrui
find
a imprimir sua saída delimitada por caracteres NUL (0x00) eread
a buscar linhas delimitadas por NUL (-d $'\0'
) sem manipular barras invertidas como escapes para outros caracteres (-r
) e não fazer nenhuma palavra dividida nas linhas (IFS=
). Como 0x00 é um byte que não pode ocorrer em nomes de arquivo ou caminhos no Unix, isso deve lidar com todos os seus problemas estranhos de nome de arquivo.fonte
-d ''
é equivalente a-d $'\0'
.