Como uso o comando “if” para várias condições?

6

Como faço isso?

if [ -f town-*.swf ]
then
mkdir towns
fi

Isso verifica se town-*.swf existe, mas eu também preciso que ele procure city-*.swf entre outros, então eu preciso de algo assim:

if [ -f town-*.swf, city-*.swf ]
then
mkdir towns
fi
    
por DisplayName 24.10.2014 / 18:47

5 respostas

6

POSIXly, você pode usar ls

if ls town-*.swf >/dev/null 2>&1 &&
   ls city-*.swf >/dev/null 2>&1 
then
  mkdir towns
fi

ou menor se a condição:

if ls town-*.swf city-*.swf >/dev/null 2>&1

mesmo que o seu shell suporte a expansão de chaves :

if ls {town,city}-*.swf >/dev/null 2>&1
    
por 24.10.2014 / 20:00
5
if stat -t city-*.swf >/dev/null 2>&1
then
    if stat -t town-*.swf >/dev/null 2>&1
    then
       mkdir towns
    fi
fi

Como o usuário apontou nos comentários, meu comando anterior evitaria que o curinga fosse expandido. No entanto, esta nova versão deve funcionar.

Se você precisar dele com um único loop if , você pode modificar o script como

if stat -t city-*.swf >/dev/null 2>&1 && stat -t town-*.swf >/dev/null 2>&1
then
     mkdir towns
fi

Se você precisar especificar uma condição ou em vez da condição e, poderá substituir && por || .

Teste

ls
city-1.swf  city-2.swf  city-3.swf  city-4.swf  city-5.swf  sc.sh  
town-1.swf  town-2.swf  town-3.swf  town-4.swf  town-5.swf

Agora, executo o script chamado sc.sh e, em seguida, vi que o diretório towns está sendo criado com êxito.

Referências

link

    
por 24.10.2014 / 18:50
2

Na maioria dos casos, o comando test ( [ ) oferece operadores -a e -o

EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.

Mas no caso de possíveis multi-linhas você deve usar o comando que pode operar na condição (por exemplo ls )

ls {town,city}-*.swf &>/dev/null && mkdir town

Você pode usar o fato de que globbing quando não consegue encontrar a substituição permanece a string como está (no caso de * ). Então, só precisamos verificar se está em algum lugar na linha:

set -- {city,town}-*.swf 
[[ ! "$*" =~ \* ]] && mkdir town

Ou use case (conforme oferecido nos comentários acima)

case $(ls) in
  *city-*.swf*town-*.swf*) mkdir town ;;
esac
    
por 25.10.2014 / 14:25
1

POSIX define a opção -p para o utilitário pathchk , então ...

  • -p Em vez de executar verificações com base no sistema de arquivos subjacente, escreva um diagnóstico para cada operando de nome de caminho que:

    • É maior que {_POSIX_PATH_MAX} bytes (consulte Valores Mínimos no volume de Definições Base do IEEE Std 1003.1-2001, Capítulo 13, Cabeçalhos,)

    • Contém qualquer componente com mais de {_POSIX_NAME_MAX} bytes

    • Contém qualquer caractere em qualquer componente que não esteja no conjunto de caracteres de nome de arquivo portátil

Se os nomes de arquivos que você está procurando devem corresponder apenas aos caracteres no conjunto de caracteres portátil do arquivo - que é composto de letras e dígitos ASCII e ._-/ - então o seguinte comando funcionará bem any sem ter que fazer mais stat() chamadas do que a shell faz para glob:

if    pathchk -p town-*.swf city-*.swf
then  mkdir towns
fi

Outra maneira é globar o nome do caminho duas vezes - uma vez para um valor já conhecido e outra para o desconhecido. Se o valor conhecido glob não for retirado, é porque o valor desconhecido não foi resolvido.

Considere o seguinte:

mkdir test
touch test/testfile1
echo tes[t]/test*1 tes[t]/test*2

OUTPUT

test/testfile1 tes[t]/test*2

Aqui, sabemos que o caminho test existe e, portanto, podemos testar sua resolução ao tentar corresponder à resolução do caminho desconhecido.

Por exemplo, suponhamos que seu diretório de trabalho atual seja composto inteiramente de nomes de caminho que não terminem com ? e não haja caminhos únicos que façam isso. Esta não é uma suposição tão grande para fazer - pode até ser assegurada como:

cd /tmp/no_question_mark\? && {
    $_handle_it || exit
};  ln -s "$PWD" /tmp/no_question_marks
    cd /tmp/no_question_marks

Essa suposição feita, você pode fazer algo como:

set "${PWD%?}"?/town-*.swf "${PWD%?}"?/city-*.swf
case "$*" in (*\?/*) ! echo 'missed at least one...';;
(*) echo 'got em all!'; mkdir towns;;
esac
    
por 25.10.2014 / 02:42
0

Aqui está uma solução que tem um impacto menor do que executar o comando externo ls , além de ser mais portável do que uma solução baseada em stat (que difere do SO para o SO).

#!/bin/bash

found=false
for _ in town-*.swf, city-*.swf do
  found=true; break
done

if $found; then
  echo "Yup!"
fi

O sublinhado é uma variável descartável. O for loop é uma maneira fácil de expandir sua lista de arquivos, e o break garante que você não perderá ciclos percorrendo uma longa lista de arquivos. Os executáveis true e false podem ser encontrados em /bin/ ou /usr/bin/ e podem ser substituídos por bash builtins ou funções se você preferir essa otimização.

Observe que isso também deve funcionar em /bin/sh . (Pelo menos, fez para mim em um par de outros sistemas operacionais.)

    
por 24.10.2014 / 23:35

Tags