Logiczne ORAZ w skrypcie bash

10

Mam ifw swoim skrypcie bash, który musi sprawdzić, czy JESZCZE z 2 plików istnieje, jeśli nie istnieją, powinien pasować do echa.

Kod mam:

if [[ ! -f /etc/benchmarking/code ]] && [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"
fi

Ale to z jakiegoś powodu nie działa.

Jestem 110% pewien, że te 2 pliki nie istnieją. Nie otrzymuję żadnych błędów, po prostu nie wchodzi if.

Jestem nowym użytkownikiem skryptów bash, więc nie jestem pewien, co może być nie tak.

Peppercat101
źródło
Nie sądzę, aby żadna z opublikowanych odpowiedzi faktycznie dotyczyła pytania. Co dzieje się, gdy próbujesz testów indywidualnie? Zrób [[ ! -f /etc/.../... ]]; echo $?dla każdego.
jw013,
Ostrzeżenie : [[ -f xxx ]]zwraca true, jeśli xxx istnieje i jest zwykłym plikiem (lub dowiązaniem symbolicznym do zwykłego pliku). Zwróci false, jeśli nie istnieje lub nie może stwierdzić, czy istnieje, czy też nie, ale nie jest zwykłym plikiem (katalog, potok, urządzenie, gniazdo ...) lub jeśli jest dowiązaniem symbolicznym do pliku, który nie istnieje lub nie może stwierdzić, czy istnieje, czy nie jest zwykłym plikiem ... [[ -e $file ]] || [[ -L $file ]]jest bliżej testu na istnienie. ls -d -- "$file" > /dev/null 2>&1jest jeszcze bliżej. Z reguły ten rodzaj testu prowadzi do warunków wyścigowych. Może jest inny sposób.
Stéphane Chazelas,

Odpowiedzi:

12

Jeśli chcesz, albo potem chcesz OR, nie AND.

if [[ ! -f /etc/benchmarking/code ]] || [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"
fi
  • Będzie to pasować, jeśli brakuje jednego lub obu plików.
  • Twój kod zostanie wydrukowany tylko matchwtedy, gdy oba nie istnieją.

Ale powiedziałeś:

Jestem 110% pewien, że te 2 pliki nie istnieją. Nie otrzymuję żadnych błędów, po prostu nie wpisuje „if”.

Twoje oświadczenie jest więc sprzeczne. Co najmniej jeden z tych plików musi istnieć, jeśli korzystasz z tego kodu.

Jeśli chcesz zobaczyć, jak ifocenia się twoje zdanie, uruchom je -x.

#!/bin/bash -x
if [[ ! -f /etc/benchmarking/code ]] && [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"
fi

Wtedy zobaczysz wykonanie.

$ ./test.sh
+ [[ ! -f /etc/benchmarking/code ]]
+ [[ ! -f /etc/benchmarking/code.class ]]
+ echo match
match
$ 
bahamat
źródło
Chcę, aby echo „pasowało”, jeśli żaden plik nie istnieje, jeśli taki istnieje, nie drukuje dopasowania. Spróbuję z -x
Peppercat101
W takim przypadku oryginalny kod powinien być w porządku. I rzeczywiście to działa dla mnie.
bahamat
3

Czy nie powinno tak być? A to plik lub B to plik, a następnie blabla.

if [[ -f /etc/benchmarking/code ]] || [[ -f /etc/benchmarking/code.class ]]; 
then  
  echo "match"
fi
stokrotka
źródło
3

Może to również działać w przypadku tego, co próbujesz zrobić. Pojedyncze nawiasy klamrowe nie są dziś powszechnie używane w bash, ale nadal jest to opcja. Użycie „-o” jest w rzeczywistości operacją „LUB”, a „!” neguje warunek.

var=/etc/benchmarking/code
[ ! -f ${var} -o -f {var}.class ] && echo "match"
slashdot
źródło
Nigdy nie używaj [w bash. Poza tym nie widzę, jak to odpowiada na pytanie.
jw013,
[ ! -f ${var} -a ! -f {var}.class ] && echo "match"powinno być. Zadanie brzmiało: jeśli (obaj) nie istnieją, powinno echo match.
hschou
0

Twój kod spełnia twoje wymagania: zostanie wydrukowany matchpod warunkiem, że nie znajdzie żadnego pliku.

Dlatego przyczyna matchnie jest drukowana jest gdzie indziej. Powinieneś potwierdzić, że blok kodu został osiągnięty, co możesz zrobić, otaczając go kilkoma komunikatami debugowania. Na przykład:

echo '@ About to enter if...fi block'
if [[ ! -f /etc/benchmarking/code ]] && [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"
fi
echo '@ Finished if...fi block'

Zwykle preferuję debugowanie wiadomości na stderr , aby uniknąć zakłócania przepływu danych na standardowe wyjście , ale unikałem tego tutaj, ponieważ powiedziałeś, że jesteś początkujący. Oto jeden przykład pokazujący, jak możesz napisać na standardowe wyjście :

echo '@ About to enter if...fi block' >&2
roaima
źródło