Eu não sei porque seus exemplos não estão funcionando. Eles trabalham aqui --- se eu usar uma expressão glob que corresponda a qualquer arquivo. Observe que, se qualquer uma das correspondências puder ser um diretório e você não quiser listar o conteúdo desse diretório, deverá adicionar um -d
flag ao seu ls
.
Você precisa estar atento ao que acontece quando sua expressão glob não corresponde a nenhum arquivo. O Bash tem uma configuração que você pode ativar com shopt -s failglob
, o que gera um erro nesse caso. Em outros shells, ou quando esta opção não foi ativada no bash, você terá a expressão glob como saída. Se você acabou de fazer um echo nonmatching_expression*
, verá o resultado "nonmatching_expression *". Se você fizer ls nonmatching_expression*
, ls deverá lançar um erro.
Como escrito, ambas as opções assumem que os nomes de arquivos não contêm espaço em branco. Isso é por causa do ls -l ... | awk '{print $9}'
. Se você sabe que seus nomes de arquivos não contêm nenhum espaço em branco, tudo bem. (Mas por que você está usando ls -l ... | awk '{print $9}'
ao invés de apenas ls
? Eu suponho que você tenha alguma razão que não se manifesta nos exemplos acima.)
Se os seus nomes de arquivos puderem conter novas linhas, as coisas ficarão muito mais difíceis --- não vou entrar no que fazer nesse caso. Se eles não contiverem novas linhas, mas puderem conter outros espaços em branco, você poderá omitir o sinalizador -l
em ls
e omitir o canal como awk. Então sua primeira opção salvaria no arquivo temporário um nome de arquivo por linha. Esses nomes de arquivos podem conter espaços ou tabulações (mas não novas linhas). Sua segunda opção também armazenaria um nome de arquivo por linha na variável, no entanto, será mais difícil trabalhar com eles.
Se você salvou a lista de nomes de arquivos em uma variável, e os nomes de arquivos podem conter algum espaço em branco, você deve sempre citar a variável ao expandi-la: use echo "$filelist"
not echo $filelist
.
Veja como eu extrairia os dados:
Opção 1:
while IFS= read -r f; do
do_stuff_with "$f"
done < tempo
Opção 2:
while IFS= read -r f; do
do_stuff_with "$f"
done << EOF
$filelist
EOF
Esses métodos permitem que você execute operações dentro do loop (modificando variáveis, alterando diretórios) que estarão visíveis para o restante do script. Se você não se importar com isso, poderá ter a seção while ... done
em um pipeline, por exemplo, assim:
echo "$filelist" | while IFS= read -r f; do
do_stuff_with "$f"
done
Nesse caso, toda a construção while ... done
é executada em um subshell e qualquer modificação nas variáveis (incluindo o loop sobre f
) só será visível dentro dessa sub-camada.
Bash e algumas outras shells possuem variáveis de array. Algumas pessoas acham que é mais fácil trabalhar com elas quando os nomes de arquivos podem conter espaços em branco. No entanto, eles são menos portáteis. E eles não podem ser exportados. (Você marcou sua pergunta como /environment-variables
, o que, para mim, implica que as variáveis serão exportadas. Mas talvez você não tenha pensado assim.) Não falarei sobre como você pode alcançar seus objetivos com variáveis de matriz. / p>
Se você sabe que não tem nenhum espaço em branco nos seus nomes de arquivos, é mais simples usar sua opção 2 e usar este método:
for f in $filenames; do
do_stuff_with $f
done
Aqui, as cotações devem ser omitidas em torno de $filenames
e são opcionais em torno de $f
.