A resposta da BLay está correta, mas para desconstruir o que está realmente acontecendo aqui (ignorando o erro de digitação do -name primária):
#!/bin/bash
while IFS= read -r -d '' file; do
files+=$file
done < <(find -type f -name '*.c' -print0)
echo "${files[@]}"
No shell iniciado pela substituição do processo ( <(...) ), o seguinte comando é analisado por bash:
find -type f -name '*.c' -print0
Como o glob *.c é citado, o bash não o o expande. No entanto, as aspas simples são removidas. Portanto, quando o processo find for iniciado, o que ele vê como sua lista de argumentos é:
-type
f
-name
*.c
-print0
Observe que esses argumentos são separados por bytes nulos , não por espaços ou novas linhas. Isso está no nível C, não no nível do shell. Isso tem a ver com a forma como os programas são executados usando execve() em C.
Agora, para contrastar, no seguinte snippet:
#!/bin/bash
find_args="-type f -name '*.c' -print0"
while IFS= read -r -d '' file; do
files+=$file
done < <(find $find_args)
echo "${files[@]}"
O valor da variável find_args está definido como:
-type f -name '*.c' -print0
(As aspas duplas não fazem parte do valor, mas os caracteres de aspas simples são . )
Quando o comando find $find_args é executado, conforme man bash , o token $find_args está sujeito à expansão de parâmetro seguido por divisão de palavras seguida por expansão do nome do caminho (também conhecido como expansão glob).
Após a expansão do parâmetro, você tem -type f -name '*.c' -print0 . Note que isso é após remoção de cotação. Assim, as aspas simples não serão removidas.
Após a divisão de palavras, você tem as seguintes palavras separadas:
-type
f
-name
'*.c'
-print0
Então vem a expansão do nome do caminho. É claro que '*.c' provavelmente não corresponderá a nada, já que você normalmente não coloca aspas nos seus nomes de arquivo, então o resultado provável será que '*.c' será passado como um padrão literal para find e, portanto, o -name primary falhará em todos os arquivos. (Teria sucesso apenas se houver um arquivo cujo nome comece com uma aspa simples e termine com os três caracteres .c' )
Editar: Na verdade, se houver um arquivo desse tipo, o glob '*.c' será expandido para corresponder a esse arquivo e qualquer outro desses arquivos e então a expansão [o nome do arquivo real] será passada para find como um padrão . Então, se o -print0 primário será alcançado ou não, depende de (a) se existe apenas um nome de arquivo, e ( b) se esse nome de arquivo, interpretado como glob, corresponde a si mesmo.
Exemplos:
Se você executar touch "'something.c'" , o glob '*.c' expandirá para 'something.c' e, em seguida, o find primary -name 'something.c' corresponderá a esse arquivo também e será impresso.
Se você executar touch "'namewithcharset[a].c'" , o glob '*.c' será expandido para esse pelo shell, mas o find primary -name 'namewithcharset[a].c' não será não correspondente - corresponderia apenas a 'namewithcharseta.c' , que não existe, por isso -print0 não seria alcançado.
Se você executar touch "'x.c'" "'y.c'" , o glob '*.c' será expandido para ambos nomes de arquivos, o que causará um erro na saída de find porque 'y.c' não é um primário válido (e não pode ser como não começa com um hífen).
Se a opção nullglob estiver definida, você terá um comportamento diferente.
Veja também: