Um comando não retorna uma sequência de caracteres (ele retorna um pequeno código de saída inteiro, geralmente 0 para êxito e 1 ou 2 em caso de falha), mas pode gerar alguns dados para inserir uma sequência.
Basile Starynkevitch
@BasileStarynkevitch esta é a coisa que eu need.I comando saber retornos saída code.But minha comandos código de saída é sempre 0.so eu preciso para controlar a saída
Anteriormente, a pergunta era como verificar se há arquivos em um diretório. O código a seguir consegue isso, mas consulte a resposta da rsp para obter uma solução melhor.
Saída vazia
Os comandos não retornam valores - eles os produzem. Você pode capturar essa saída usando substituição de comando ; por exemplo $(ls -A). Você pode testar uma cadeia de caracteres não vazia no Bash assim:
if[[ $(ls -A)]];then
echo "there are files"else
echo "no files found"fi
Note que eu usei -Aem vez de -a, uma vez que omite a corrente simbólica ( .) e pai ( ..entradas de diretório).
Nota: Conforme indicado nos comentários, a substituição de comandos não captura as novas linhas à direita . Portanto, se o comando gerar apenas novas linhas, a substituição não capturará nada e o teste retornará falso. Embora muito improvável, isso é possível no exemplo acima, pois uma única nova linha é um nome de arquivo válido! Mais informações nesta resposta .
Código de saída
Se você deseja verificar se o comando foi concluído com êxito, é possível inspecionar $?, que contém o código de saída do último comando (zero para êxito, diferente de zero para falha). Por exemplo:
Você pode omitir-n , então será apenasif [[ $(ls -A) ]]; then
usuário
6
Este método fornece false para comandos que emitem apenas novas linhas.
Ciro Santilli escreveu
89
TL; DR
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi
Agradeço ao netj
por uma sugestão para melhorar meu original: if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi
Esta é uma pergunta antiga, mas vejo pelo menos duas coisas que precisam de melhorias ou pelo menos alguns esclarecimentos.
Primeiro problema
O primeiro problema que vejo é que a maioria dos exemplos fornecidos aqui simplesmente não funciona . Eles usam os comandos ls -ale ls -Al- ambos produzem cadeias não vazias em diretórios vazios. Esses exemplos sempre relatam que existem arquivos, mesmo quando não existem .
Por esse motivo, você deve usar apenas ls -A- Por que alguém iria querer usar a -lopção que significa "usar um formato de listagem longo" quando tudo o que você quer é testar se há alguma saída ou não, afinal?
Portanto, a maioria das respostas aqui são simplesmente incorretas.
Segundo problema
O segundo problema é que, enquanto algumas respostas funcionar bem (aqueles que não usam ls -alou ls -Al, mas ls -Aem vez disso) todos eles fazem algo como isto:
executar um comando
Buffer sua saída inteira na RAM
converter a saída em uma enorme cadeia de linha única
compare essa string com uma string vazia
O que eu sugeriria fazer seria:
executar um comando
conte os caracteres em sua saída sem armazená-los
ou melhor ainda - conte o número máximo de 1 caractere using head -c1 (obrigado a netj por postar essa idéia nos comentários abaixo)
compare esse número com zero
Então, por exemplo, em vez de:
if[[ $(ls -A)]]
Eu usaria:
if[[ $(ls -A | wc -c)-ne 0]]# or:if[[ $(ls -A | head -c1 | wc -c)-ne 0]]
[[ $(... | head -c | wc -c) -gt 0 ]]ou [[ -n $(... | head -c1) ]]são melhores porque wc -cteriam que consumir toda a saída do comando.
22717 netj
@netj Esta é uma ideia muito boa. Veja minha resposta atualizada - eu adicionei sua sugestão. Muito obrigado!
Rsp #
Alguma idéia de como obter a saída?
Fahrradflucht 28/05
Eu acho que o original (sem cabeça) é melhor no caso geral. Nem sempre é uma boa ideia interromper o comando assim que ele começa a escrever a saída!
Stk
@stk A maioria dos programas sai com segurança após receber um sinal de interrupção.
cambunctious
40
if[-z "$(ls -lA)"];then
echo "no files found"else
echo "There are files"fi
Isso executará o comando e verificará se a saída retornada (string) tem um comprimento zero. Você pode verificar as páginas de manual 'teste' para outros sinalizadores.
Use o "" em volta do argumento que está sendo verificado, caso contrário, resultados vazios resultarão em um erro de sintaxe, pois não há um segundo argumento (para verificar) fornecido!
Nota: isso ls -lasempre retorna .e, ..portanto, usá-lo não funciona, consulte as páginas de manual . Além disso, embora isso possa parecer conveniente e fácil, suponho que ele se quebre facilmente. Escrever um pequeno script / aplicativo que retorne 0 ou 1, dependendo do resultado, é muito mais confiável!
Você pode preferir usar $(em vez de crase, porque $(ninho melhor
Basile Starynkevitch
Você está certo, é uma prática recomendada usá-los sempre, embora não precisemos de aninhamento aqui.
Veger 27/08/12
23
Para aqueles que desejam uma solução elegante e independente da versão do bash (de fato, deve funcionar em outros shells modernos) e aqueles que gostam de usar one-liners para tarefas rápidas. Aqui vamos nós!
ls | grep .&& echo 'files found'|| echo 'files not found'
(observe como um dos comentários mencionados ls -ale, de fato, apenas -le -atodos retornarão algo, por isso, na minha resposta,ls
Se você usar grep -q ^, os caracteres de nova linha também serão correspondidos e o grep não imprimirá nada na saída padrão. Além disso, ele será encerrado assim que receber qualquer entrada, em vez de aguardar o término do fluxo de entrada.
mortehu 12/06
Deve começar ls -Ase você quiser incluir arquivos de ponto (ou diretórios)
Isso não funciona: o comando lsnunca está sendo executado. Você só verifica se a expansão da variávelLS não está vazia.
Gniourf_gniourf
1
@gniourf_gniourf - o que faz você pensar isso? O encantamento crase é, reconhecidamente, não tão bonita ou flexível quanto $ (), mas funciona ...
tink
A -aopção nunca retornará conteúdo (isto é, retornará conteúdo, independentemente de haver arquivos ou não), pois sempre há os diretórios implícitos .e ..presentes.
wrlee 18/02
3
Aqui está uma solução para casos mais extremos:
if[`command | head -c1 | wc -c`-gt 0];then...;fi
Isso vai funcionar
para todas as conchas Bourne;
se a saída do comando for todos os zeros;
eficientemente, independentemente do tamanho da saída;
Contudo,
o comando ou seus subprocessos serão eliminados assim que alguma coisa for emitida.
Todas as respostas dadas até agora tratam de comandos que terminam e emitem uma sequência não vazia.
A maioria é quebrada nos seguintes sentidos:
Eles não lidam corretamente com comandos que produzem apenas novas linhas;
a partir do Bash≥4,4, a maioria enviará um erro padrão de spam se o comando gerar bytes nulos (pois eles usam substituição de comando);
a maioria consumirá todo o fluxo de saída, portanto esperará até o comando terminar antes de responder. Alguns comandos nunca terminam (tente, por exemplo, yes).
Portanto, para corrigir todos esses problemas e responder com eficiência à seguinte pergunta,
Como posso testar se um comando gera uma string vazia?
Você também pode adicionar algum tempo limite para testar se um comando gera uma seqüência de caracteres não vazia dentro de um determinado tempo, usando reada -topção 's . Por exemplo, por um tempo limite de 2,5 segundos:
Penso que esta resposta é subestimada. I foi o desempenho de testes de algumas das soluções aqui utilizando 100 iterações para cada um dos cenários de entrada (3 seq 1 10000000, seq 1 20, e printf""). A única combinação que essa abordagem de leitura não venceu foi com a -z "$(command)"abordagem de uma entrada vazia. Mesmo assim, perde apenas entre 10 e 15%. Eles parecem se equilibrar seq 1 10. Independentemente disso, a -z "$(command)"abordagem se torna tão lenta quanto o tamanho da entrada aumenta, que eu evitaria usá-la para qualquer entrada de tamanho variável.
Abathur
0
Aqui está uma abordagem alternativa que grava o std-out e std-err de algum comando em um arquivo temporário e, em seguida, verifica se esse arquivo está vazio. Um benefício dessa abordagem é que ela captura as duas saídas e não usa subcascas ou tubos. Esses últimos aspectos são importantes porque eles podem interferir no manuseio de saída da saída do bash (por exemplo, aqui )
tmpfile=$(mktemp)
some-command &>"$tmpfile"if[[ $?!=0]];then
echo "Command failed"elif[[-s "$tmpfile"]];then
echo "Command generated output"else
echo "Command has no output"fi
rm -f "$tmpfile"
ifne
para isso. joeyh.name/code/moreutilsRespostas:
Anteriormente, a pergunta era como verificar se há arquivos em um diretório. O código a seguir consegue isso, mas consulte a resposta da rsp para obter uma solução melhor.
Saída vazia
Os comandos não retornam valores - eles os produzem. Você pode capturar essa saída usando substituição de comando ; por exemplo
$(ls -A)
. Você pode testar uma cadeia de caracteres não vazia no Bash assim:Note que eu usei
-A
em vez de-a
, uma vez que omite a corrente simbólica (.
) e pai (..
entradas de diretório).Nota: Conforme indicado nos comentários, a substituição de comandos não captura as novas linhas à direita . Portanto, se o comando gerar apenas novas linhas, a substituição não capturará nada e o teste retornará falso. Embora muito improvável, isso é possível no exemplo acima, pois uma única nova linha é um nome de arquivo válido! Mais informações nesta resposta .
Código de saída
Se você deseja verificar se o comando foi concluído com êxito, é possível inspecionar
$?
, que contém o código de saída do último comando (zero para êxito, diferente de zero para falha). Por exemplo:Mais informações aqui .
fonte
-n
, então será apenasif [[ $(ls -A) ]]; then
TL; DR
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi
Agradeço ao netj por uma sugestão para melhorar meu original:
if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi
Esta é uma pergunta antiga, mas vejo pelo menos duas coisas que precisam de melhorias ou pelo menos alguns esclarecimentos.
Primeiro problema
O primeiro problema que vejo é que a maioria dos exemplos fornecidos aqui simplesmente não funciona . Eles usam os comandos
ls -al
els -Al
- ambos produzem cadeias não vazias em diretórios vazios. Esses exemplos sempre relatam que existem arquivos, mesmo quando não existem .Por esse motivo, você deve usar apenas
ls -A
- Por que alguém iria querer usar a-l
opção que significa "usar um formato de listagem longo" quando tudo o que você quer é testar se há alguma saída ou não, afinal?Portanto, a maioria das respostas aqui são simplesmente incorretas.
Segundo problema
O segundo problema é que, enquanto algumas respostas funcionar bem (aqueles que não usam
ls -al
ouls -Al
, masls -A
em vez disso) todos eles fazem algo como isto:O que eu sugeriria fazer seria:
using head -c1
(obrigado a netj por postar essa idéia nos comentários abaixo)
Então, por exemplo, em vez de:
Eu usaria:
Ao invés de:
Eu usaria:
e assim por diante.
Para saídas pequenas, pode não ser um problema, mas para saídas maiores a diferença pode ser significativa:
Compare com:
E ainda melhor:
Exemplo completo
Exemplo atualizado da resposta de Will Vousden:
Atualizado novamente após sugestões de netj :
Atualização adicional por jakeonfire :
grep
sairá com falha se não houver correspondência. Podemos tirar vantagem disso para simplificar um pouco a sintaxe:Descartando espaço em branco
Se o comando que você está testando pode gerar algum espaço em branco que você deseja tratar como uma sequência vazia, em vez de:
você poderia usar:
ou com
head -c1
:ou algo assim.
Resumo
Primeiro, use um comando que funcione .
Segundo, evite o armazenamento desnecessário na RAM e o processamento de dados potencialmente enormes.
A resposta não especificou que a saída é sempre pequena; portanto, uma possibilidade de saída grande também deve ser considerada.
fonte
[[ $(... | head -c | wc -c) -gt 0 ]]
ou[[ -n $(... | head -c1) ]]
são melhores porquewc -c
teriam que consumir toda a saída do comando.Isso executará o comando e verificará se a saída retornada (string) tem um comprimento zero. Você pode verificar as páginas de manual 'teste' para outros sinalizadores.
Use o "" em volta do argumento que está sendo verificado, caso contrário, resultados vazios resultarão em um erro de sintaxe, pois não há um segundo argumento (para verificar) fornecido!
Nota: isso
ls -la
sempre retorna.
e,..
portanto, usá-lo não funciona, consulte as páginas de manual . Além disso, embora isso possa parecer conveniente e fácil, suponho que ele se quebre facilmente. Escrever um pequeno script / aplicativo que retorne 0 ou 1, dependendo do resultado, é muito mais confiável!fonte
$(
em vez de crase, porque$(
ninho melhorPara aqueles que desejam uma solução elegante e independente da versão do bash (de fato, deve funcionar em outros shells modernos) e aqueles que gostam de usar one-liners para tarefas rápidas. Aqui vamos nós!
(observe como um dos comentários mencionados
ls -al
e, de fato, apenas-l
e-a
todos retornarão algo, por isso, na minha resposta,ls
fonte
grep -q ^
, os caracteres de nova linha também serão correspondidos e o grep não imprimirá nada na saída padrão. Além disso, ele será encerrado assim que receber qualquer entrada, em vez de aguardar o término do fluxo de entrada.ls -A
se você quiser incluir arquivos de ponto (ou diretórios)Manual de Referência do Bash
6.4 Expressões condicionais de bash
Você pode usar a versão abreviada:
fonte
string
é apenas um sinônimo-n string
.Como Jon Lin comentou,
ls -al
sempre produzirá (para.
e..
). Você desejals -Al
evitar esses dois diretórios.Você pode, por exemplo, colocar a saída do comando em uma variável do shell:
Uma notação mais antiga e não aninhada é
mas eu prefiro a notação aninhada
$(
...)
Você pode testar se essa variável não está vazia
E você pode combinar tanto quanto
if [ -n "$(ls -Al)" ]; then
fonte
Suponho que você queira a saída do
ls -al
comando, portanto, no bash, você terá algo como:fonte
ls
nunca está sendo executado. Você só verifica se a expansão da variávelLS
não está vazia.-a
opção nunca retornará conteúdo (isto é, retornará conteúdo, independentemente de haver arquivos ou não), pois sempre há os diretórios implícitos.
e..
presentes.Aqui está uma solução para casos mais extremos:
Isso vai funcionar
Contudo,
fonte
Todas as respostas dadas até agora tratam de comandos que terminam e emitem uma sequência não vazia.
A maioria é quebrada nos seguintes sentidos:
yes
).Portanto, para corrigir todos esses problemas e responder com eficiência à seguinte pergunta,
você pode usar:
Você também pode adicionar algum tempo limite para testar se um comando gera uma seqüência de caracteres não vazia dentro de um determinado tempo, usando
read
a-t
opção 's . Por exemplo, por um tempo limite de 2,5 segundos:Observação. Se você acha que precisa determinar se um comando gera uma sequência não vazia, é muito provável que tenha um problema XY.
fonte
seq 1 10000000
,seq 1 20
, eprintf""
). A única combinação que essa abordagem de leitura não venceu foi com a-z "$(command)"
abordagem de uma entrada vazia. Mesmo assim, perde apenas entre 10 e 15%. Eles parecem se equilibrarseq 1 10
. Independentemente disso, a-z "$(command)"
abordagem se torna tão lenta quanto o tamanho da entrada aumenta, que eu evitaria usá-la para qualquer entrada de tamanho variável.Aqui está uma abordagem alternativa que grava o std-out e std-err de algum comando em um arquivo temporário e, em seguida, verifica se esse arquivo está vazio. Um benefício dessa abordagem é que ela captura as duas saídas e não usa subcascas ou tubos. Esses últimos aspectos são importantes porque eles podem interferir no manuseio de saída da saída do bash (por exemplo, aqui )
fonte
Às vezes, você deseja salvar a saída, se não estiver vazia, para passá-la para outro comando. Nesse caso, você poderia usar algo como
Dessa forma, o
rm
comando não será interrompido se a lista estiver vazia.fonte