Eu pensei que isso seria simples - mas está se mostrando mais complexo do que eu esperava.
Eu quero percorrer todos os arquivos de um tipo específico em um diretório, então escrevo isto:
#!/bin/bash
for fname in *.zip ; do
echo current file is ${fname}
done
Isso funciona desde que haja pelo menos um arquivo correspondente no diretório No entanto, se não houver arquivos correspondentes, recebo o seguinte:
current file is *.zip
Eu então tentei:
#!/bin/bash
FILES=`ls *.zip`
for fname in "${FILES}" ; do
echo current file is ${fname}
done
Enquanto o corpo do loop não é executado quando não há arquivos, recebo um erro de ls:
ls: *.zip: No such file or directory
Como escrevo um loop que não lida corretamente com arquivos correspondentes?
shopt -s nullglob
antes de executar o loop for.FILES=
ls * .zip,; for fname in "${FILES}"...
mas funciona como esperado comfor fname in *.zip ; do....
for file in *.zip
, não`ls ...`
. A sugestão do @ cuonglm é*.zip
expandir para nada quando o padrão não corresponder a nenhum arquivo.ls
sem argumentos lista o diretório atual.ls
geralmente deve ser evitada: Por que não analisarls
? ; veja também o link no topo da página para o artigo ParsingLs do BashGuide .Respostas:
Em
bash
, você pode definir anullglob
opção para que um padrão que corresponda a nada "desapareça", em vez de ser tratado como uma sequência literal:No shell script POSIX, você apenas verifica se
fname
existe (e ao mesmo tempo com[ -f ]
, verifique se é um arquivo regular (ou um link simbólico para um arquivo normal) e não outros tipos, como diretório / fifo / device ...):Substitua
[ -f "$fname" ]
por[ -e "$fname" ] || [ -L "$fname ]
se desejar fazer um loop sobre todos os arquivos (não ocultos) cujo nome termina.zip
independentemente do tipo.Substitua
*.zip
por.*.zip .zip *.zip
se você também deseja considerar arquivos ocultos cujo nome termina em.zip
.fonte
shopt -s nullglob
não funcionou para mim no Ubuntu 17.04, mas[ -f "$fname" ] || continue
funcionou bem.bash
.Em um comentário aqui, você menciona a invocação de uma função ...
fonte
Use find
Você DEVE exportar sua função shell
export -f
para que isso funcione. Agorafind
executa obash
que executa sua função shell e permanece apenas no nível de diretório atual.fonte
Ao invés de:
Experimentar:
Dessa forma, se ls falhar (o que ocorre no seu caso), ele receberá a saída com falha e retornará como uma variável em branco.
Você pode adicionar alguma lógica a isso para fazer com que ele retorne "Nenhum arquivo encontrado"
Dessa forma, se o comando anterior tiver êxito (encerrado com um valor 0), ele imprimirá o arquivo atual; caso contrário, imprimirá "Nenhum arquivo encontrado"
fonte
grep
) em vez de tentar corrigir o problema usando uma ferramenta melhor (find
) ou alterar a configuração relevante para a solução atual (comshopt -s nullglob
)shopt -s nullglob
isso não funciona. Tenteifind
verificar minha resposta e ela continuou falhando. Acho que por causa da coisa de exportação que Dani disse.