Polecenie nie zwraca łańcucha (zwraca kod zakończenia małej liczby całkowitej, zwykle 0 dla sukcesu i 1 lub 2 w przypadku awarii), ale może wysyłać pewne dane, aby umieścić w ciągu.
Basile Starynkevitch
@BasileStarynkevitch to jest to, czego potrzebuję. Wiem, że polecenie zwraca kod wyjścia. Ale moje kody wyjścia zawsze wynoszą 0. więc muszę kontrolować dane wyjściowe
Poprzednio pytanie dotyczyło sposobu sprawdzania, czy w katalogu znajdują się pliki. Poniższy kod osiąga to, ale zobacz odpowiedź rsp na lepsze rozwiązanie.
Pusty wynik
Polecenia nie zwracają wartości - wysyłają je. Możesz przechwycić ten wynik za pomocą podstawiania poleceń ; np $(ls -A). Możesz przetestować pod kątem niepustego ciągu w Bash w następujący sposób:
if[[ $(ls -A)]];then
echo "there are files"else
echo "no files found"fi
Zauważ, że użyłem -Araczej niż -a, ponieważ pomija symboliczne wpisy katalogu current ( .) i parent ( ..).
Uwaga: Jak wskazano w komentarzach, podstawianie poleceń nie przechwytuje końcowych znaków nowej linii . Dlatego jeśli polecenie wyprowadza tylko znaki nowej linii, podstawienie niczego nie przechwyci, a test zwróci false. Chociaż jest to bardzo mało prawdopodobne, jest to możliwe w powyższym przykładzie, ponieważ pojedyncza nowa linia jest prawidłową nazwą pliku! Więcej informacji w tej odpowiedzi .
Kod wyjścia
Jeśli chcesz sprawdzić, czy polecenie zakończyło się pomyślnie, możesz sprawdzić $?, który zawiera kod zakończenia ostatniego polecenia (zero dla sukcesu, niezerowe dla niepowodzenia). Na przykład:
Ty można pominąć-n , więc będzie to po prostuif [[ $(ls -A) ]]; then
użytkownik
6
Ta metoda podaje wartość false dla poleceń, które wypisują tylko znaki nowej linii.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
89
TL; DR
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi
Dzięki netj
za sugestię ulepszenia mojego oryginału: if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi
To stare pytanie, ale widzę co najmniej dwie rzeczy, które wymagają poprawy lub przynajmniej wyjaśnienia.
Pierwszy problem
Pierwszy problem, jaki widzę, to to, że większość podanych tu przykładów po prostu nie działa . Używają poleceń ls -ali ls -Al- z których oba wypisują niepuste ciągi znaków w pustych katalogach. Te przykłady zawsze informują, że istnieją pliki, nawet jeśli ich nie ma .
Z tego powodu powinieneś użyć właśnie ls -A- Dlaczego ktokolwiek miałby chcieć użyć -lprzełącznika, co oznacza „użyj długiego formatu listowania”, gdy wszystko, czego potrzebujesz, to przetestować, czy jest jakikolwiek wynik, czy nie?
Dlatego większość odpowiedzi tutaj jest po prostu niepoprawna.
Drugi problem
Drugim problemem jest to, że podczas gdy niektóre odpowiedzi działać dobrze (te, które nie używać ls -alalbo ls -Alale ls -Azamiast) wszyscy robią coś takiego:
uruchom polecenie
buforować całe wyjście w pamięci RAM
przekonwertować dane wyjściowe na ogromny ciąg jednowierszowy
porównaj ten ciąg z pustym ciągiem
Sugerowałbym zamiast tego:
uruchom polecenie
policz znaki na wyjściu bez ich przechowywania
lub jeszcze lepiej - policz maksymalnie maksymalnie 1 znak using head -c1 (dzięki netj za opublikowanie tego pomysłu w komentarzach poniżej)
porównaj tę liczbę z zerem
Na przykład zamiast:
if[[ $(ls -A)]]
Użyłbym:
if[[ $(ls -A | wc -c)-ne 0]]# or:if[[ $(ls -A | head -c1 | wc -c)-ne 0]]
[[ $(... | head -c | wc -c) -gt 0 ]]lub [[ -n $(... | head -c1) ]]są lepsze, ponieważ wc -cmusiałyby zużywać całą moc polecenia.
netj
@netj To bardzo dobry pomysł. Zobacz moją zaktualizowaną odpowiedź - dodałem twoją sugestię. Wielkie dzięki!
rsp
Jakieś pomysły, jak zdobyć wynik?
fahrradflucht
Myślę, że oryginał (bez głowy) jest lepszy w ogólnym przypadku. Nie zawsze dobrym pomysłem jest zabicie polecenia, gdy tylko zacznie zapisywać dane wyjściowe!
stk
@stk Większość programów bezpiecznie zakończy działanie po odebraniu sygnału zabicia.
kambuzowy
40
if[-z "$(ls -lA)"];then
echo "no files found"else
echo "There are files"fi
Spowoduje to uruchomienie polecenia i sprawdzenie, czy zwrócone dane wyjściowe (ciąg) mają zerową długość. Możesz sprawdzić strony podręcznika „test” pod kątem innych flag.
Użyj „” wokół sprawdzanego argumentu, w przeciwnym razie puste wyniki spowodują błąd składniowy, ponieważ nie podano drugiego argumentu (do sprawdzenia)!
Uwaga: to ls -lazawsze zwraca .i ..tak za pomocą to nie zadziała, zobacz ls stron podręcznika . Ponadto, chociaż może się to wydawać wygodne i łatwe, przypuszczam, że łatwo się zepsuje. Pisanie małego skryptu / aplikacji, która zwraca 0 lub 1 w zależności od wyniku, jest znacznie bardziej niezawodne!
Może wolisz używać $(zamiast cudzysłowu, ponieważ $(lepiej zagnieżdżaj
Basile Starynkevitch
Masz rację, lepiej jest używać ich zawsze, chociaż nie musimy tutaj zagnieżdżać się.
Veger
23
Dla tych, którzy chcą eleganckiego, niezależnego od wersji bash rozwiązania (w rzeczywistości powinny działać w innych nowoczesnych powłokach) i dla tych, którzy lubią używać jednowarstwowych do szybkich zadań. No to ruszamy!
ls | grep .&& echo 'files found'|| echo 'files not found'
(uwaga jak jeden z komentarzy wspomniano, ls -alaw rzeczywistości po prostu -li -abędzie wszystko powrót coś, więc w mojej odpowiedzi używać prostychls
Jeśli użyjesz grep -q ^zamiast tego, znaki nowego wiersza również zostaną dopasowane, a grep nie wydrukuje niczego na standardowym wyjściu. Ponadto zakończy działanie, gdy tylko odbierze dane wejściowe, zamiast czekać na zakończenie strumienia wejściowego.
mortehu
Powinieneś zacząć od, ls -Ajeśli chcesz dołączyć pliki kropek (lub katalogi)
Wszystkie dotychczasowe odpowiedzi dotyczą poleceń kończących i generujących niepusty ciąg znaków.
Większość jest rozbita na następujące zmysły:
Nie radzą sobie właściwie z poleceniami wypisującymi tylko znaki nowej linii;
począwszy od Bash ≥4.4 większość będzie spamować standardowy błąd, jeśli polecenie wyda bajty zerowe (ponieważ używają podstawienia polecenia);
większość przepełnia pełny strumień wyjściowy, więc przed odpowiedzią zaczeka na zakończenie polecenia. Niektóre polecenia nigdy się nie kończą (spróbuj np yes.).
Aby rozwiązać wszystkie te problemy i skutecznie odpowiedzieć na następujące pytanie,
Jak mogę sprawdzić, czy polecenie generuje pusty ciąg?
Można też dodać trochę limitu czasu, tak aby sprawdzić, czy polecenie wyprowadza niepusty ciąg w danym czasie, przy użyciu read„s -topcję. Na przykład po upływie 2,5 sekundy:
Myślę, że ta odpowiedź jest raczej niedoceniana. Ja wydajności badań niektórych rozwiązań tutaj po 100 iteracji dla każdej z 3 scenariuszy wejściowych ( seq 1 10000000, seq 1 20i printf""). Jedynym pojedynkiem, w którym ta metoda odczytu nie wygrała, było -z "$(command)"podejście z pustym wejściem. Nawet wtedy traci tylko około 10-15%. Wydaje się, że się załamują seq 1 10. Niezależnie od tego -z "$(command)"podejście staje się tak wolne, jak rośnie rozmiar wejściowy, że unikałbym używania go do wprowadzania danych o zmiennej wielkości.
abathur
0
Oto alternatywne podejście, które zapisuje std-out i std-err niektórych poleceń w pliku tymczasowym, a następnie sprawdza, czy ten plik jest pusty. Zaletą tego podejścia jest to, że przechwytuje oba wyjścia i nie używa podpowłok ani rur. Te ostatnie aspekty są ważne, ponieważ mogą zakłócać obsługę wychodzenia z wychwytu bash (np. Tutaj )
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
do tego narzędzie . joeyh.name/code/moreutilsOdpowiedzi:
Poprzednio pytanie dotyczyło sposobu sprawdzania, czy w katalogu znajdują się pliki. Poniższy kod osiąga to, ale zobacz odpowiedź rsp na lepsze rozwiązanie.
Pusty wynik
Polecenia nie zwracają wartości - wysyłają je. Możesz przechwycić ten wynik za pomocą podstawiania poleceń ; np
$(ls -A)
. Możesz przetestować pod kątem niepustego ciągu w Bash w następujący sposób:Zauważ, że użyłem
-A
raczej niż-a
, ponieważ pomija symboliczne wpisy katalogu current (.
) i parent (..
).Uwaga: Jak wskazano w komentarzach, podstawianie poleceń nie przechwytuje końcowych znaków nowej linii . Dlatego jeśli polecenie wyprowadza tylko znaki nowej linii, podstawienie niczego nie przechwyci, a test zwróci false. Chociaż jest to bardzo mało prawdopodobne, jest to możliwe w powyższym przykładzie, ponieważ pojedyncza nowa linia jest prawidłową nazwą pliku! Więcej informacji w tej odpowiedzi .
Kod wyjścia
Jeśli chcesz sprawdzić, czy polecenie zakończyło się pomyślnie, możesz sprawdzić
$?
, który zawiera kod zakończenia ostatniego polecenia (zero dla sukcesu, niezerowe dla niepowodzenia). Na przykład:Więcej informacji tutaj .
źródło
-n
, więc będzie to po prostuif [[ $(ls -A) ]]; then
TL; DR
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi
Dzięki netj za sugestię ulepszenia mojego oryginału:
if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi
To stare pytanie, ale widzę co najmniej dwie rzeczy, które wymagają poprawy lub przynajmniej wyjaśnienia.
Pierwszy problem
Pierwszy problem, jaki widzę, to to, że większość podanych tu przykładów po prostu nie działa . Używają poleceń
ls -al
ils -Al
- z których oba wypisują niepuste ciągi znaków w pustych katalogach. Te przykłady zawsze informują, że istnieją pliki, nawet jeśli ich nie ma .Z tego powodu powinieneś użyć właśnie
ls -A
- Dlaczego ktokolwiek miałby chcieć użyć-l
przełącznika, co oznacza „użyj długiego formatu listowania”, gdy wszystko, czego potrzebujesz, to przetestować, czy jest jakikolwiek wynik, czy nie?Dlatego większość odpowiedzi tutaj jest po prostu niepoprawna.
Drugi problem
Drugim problemem jest to, że podczas gdy niektóre odpowiedzi działać dobrze (te, które nie używać
ls -al
albols -Al
alels -A
zamiast) wszyscy robią coś takiego:Sugerowałbym zamiast tego:
using head -c1
(dzięki netj za opublikowanie tego pomysłu w komentarzach poniżej)
Na przykład zamiast:
Użyłbym:
Zamiast:
Użyłbym:
i tak dalej.
W przypadku małych wyjść może to nie stanowić problemu, ale w przypadku większych wyjść różnica może być znacząca:
Porównaj to z:
A nawet lepiej:
Pełny przykład
Zaktualizowany przykład z odpowiedzi Will Vousden:
Zaktualizowany ponownie po sugestiach netj :
Dodatkowa aktualizacja autorstwa jakeonfire :
grep
zakończy działanie z błędem, jeśli nie ma dopasowania. Możemy to wykorzystać, aby nieco uprościć składnię:Odrzucanie białych znaków
Jeśli testowane polecenie może wygenerować spację, którą chcesz traktować jako pusty ciąg, to zamiast:
możesz użyć:
lub z
head -c1
:czy jakoś tak.
Podsumowanie
Najpierw użyj polecenia, które działa .
Po drugie, unikaj niepotrzebnego przechowywania w pamięci RAM i przetwarzania potencjalnie dużych danych.
W odpowiedzi nie określono, że wyjście jest zawsze małe, dlatego należy wziąć pod uwagę także możliwość uzyskania dużych wyników.
źródło
[[ $(... | head -c | wc -c) -gt 0 ]]
lub[[ -n $(... | head -c1) ]]
są lepsze, ponieważwc -c
musiałyby zużywać całą moc polecenia.Spowoduje to uruchomienie polecenia i sprawdzenie, czy zwrócone dane wyjściowe (ciąg) mają zerową długość. Możesz sprawdzić strony podręcznika „test” pod kątem innych flag.
Użyj „” wokół sprawdzanego argumentu, w przeciwnym razie puste wyniki spowodują błąd składniowy, ponieważ nie podano drugiego argumentu (do sprawdzenia)!
Uwaga: to
ls -la
zawsze zwraca.
i..
tak za pomocą to nie zadziała, zobacz ls stron podręcznika . Ponadto, chociaż może się to wydawać wygodne i łatwe, przypuszczam, że łatwo się zepsuje. Pisanie małego skryptu / aplikacji, która zwraca 0 lub 1 w zależności od wyniku, jest znacznie bardziej niezawodne!źródło
$(
zamiast cudzysłowu, ponieważ$(
lepiej zagnieżdżajDla tych, którzy chcą eleganckiego, niezależnego od wersji bash rozwiązania (w rzeczywistości powinny działać w innych nowoczesnych powłokach) i dla tych, którzy lubią używać jednowarstwowych do szybkich zadań. No to ruszamy!
(uwaga jak jeden z komentarzy wspomniano,
ls -al
aw rzeczywistości po prostu-l
i-a
będzie wszystko powrót coś, więc w mojej odpowiedzi używać prostychls
źródło
grep -q ^
zamiast tego, znaki nowego wiersza również zostaną dopasowane, a grep nie wydrukuje niczego na standardowym wyjściu. Ponadto zakończy działanie, gdy tylko odbierze dane wejściowe, zamiast czekać na zakończenie strumienia wejściowego.ls -A
jeśli chcesz dołączyć pliki kropek (lub katalogi)Podręcznik referencyjny Bash
6.4 Wyrażenia warunkowe Bash
Możesz użyć wersji skróconej:
źródło
string
to tylko synonim-n string
.Jak skomentował Jon Lin,
ls -al
zawsze będzie generował (dla.
i..
). Chceszls -Al
uniknąć tych dwóch katalogów.Możesz na przykład umieścić wynik polecenia w zmiennej powłoki:
Starsza notacja, której nie można zagnieździć, to
ale wolę notację zagnieżdżoną
$(
...)
Możesz sprawdzić, czy ta zmienna nie jest pusta
I możesz połączyć oba jako
if [ -n "$(ls -Al)" ]; then
źródło
Zgaduję, że chcesz
ls -al
otrzymać wynik polecenia, więc w bash miałbyś coś takiego:źródło
ls
nigdy nie jest wykonywane. Sprawdzasz tylko, czy rozwinięcie zmiennejLS
nie jest puste.-a
Przełącznik nigdy nie powróci zawartości (tj powróci treści czy istnieją pliki lub nie), ponieważ zawsze istnieje niejawna.
i..
katalogi obecny.Oto rozwiązanie dla bardziej ekstremalnych przypadków:
To zadziała
jednak,
źródło
Wszystkie dotychczasowe odpowiedzi dotyczą poleceń kończących i generujących niepusty ciąg znaków.
Większość jest rozbita na następujące zmysły:
yes
.).Aby rozwiązać wszystkie te problemy i skutecznie odpowiedzieć na następujące pytanie,
możesz użyć:
Można też dodać trochę limitu czasu, tak aby sprawdzić, czy polecenie wyprowadza niepusty ciąg w danym czasie, przy użyciu
read
„s-t
opcję. Na przykład po upływie 2,5 sekundy:Uwaga. Jeśli uważasz, że musisz ustalić, czy polecenie generuje niepusty ciąg, prawdopodobnie masz problem z XY.
źródło
seq 1 10000000
,seq 1 20
iprintf""
). Jedynym pojedynkiem, w którym ta metoda odczytu nie wygrała, było-z "$(command)"
podejście z pustym wejściem. Nawet wtedy traci tylko około 10-15%. Wydaje się, że się załamująseq 1 10
. Niezależnie od tego-z "$(command)"
podejście staje się tak wolne, jak rośnie rozmiar wejściowy, że unikałbym używania go do wprowadzania danych o zmiennej wielkości.Oto alternatywne podejście, które zapisuje std-out i std-err niektórych poleceń w pliku tymczasowym, a następnie sprawdza, czy ten plik jest pusty. Zaletą tego podejścia jest to, że przechwytuje oba wyjścia i nie używa podpowłok ani rur. Te ostatnie aspekty są ważne, ponieważ mogą zakłócać obsługę wychodzenia z wychwytu bash (np. Tutaj )
źródło
Czasami chcesz zapisać wynik, jeśli nie jest pusty, aby przekazać go do innego polecenia. Jeśli tak, możesz użyć czegoś takiego
W ten sposób
rm
polecenie nie zawiesi się, jeśli lista będzie pusta.źródło