Unikanie błędów spowodowanych nierozwiniętą gwiazdką

16

W bash często używam pętli for, takich jak następujące

for file in *.type; do 
  sommecommand "$file"; 
done;

wykonać operację dla wszystkich pasujących plików *.type. Jeśli w katalogach roboczych nie zostanie znaleziony plik z takim zakończeniem, gwiazdka nie zostanie rozwinięta i zwykle pojawia się komunikat o błędzie informujący, że ktoś nie znalazł pliku. Mogę od razu wymyślić kilka sposobów uniknięcia tego błędu. Ale dodanie warunku nie wydaje się zbyt eleganckie. Czy istnieje krótki i czysty sposób na osiągnięcie tego?

wysoki
źródło

Odpowiedzi:

20

Tak, uruchom następujące polecenie:

shopt -s nullglob

anuluje dopasowanie i nie zostanie wyzwolony żaden błąd.

  • jeśli chcesz to zachowanie domyślnie, dodaj polecenie w swoim ~/.bashrc
  • jeśli chcesz wykryć zerowy glob w powłoce POSIX, spróbuj

    for i in *.txt; do
      [ "$i" = '*.txt' ] && [ ! -e '*.txt' ] && continue
    done

Zobacz http://mywiki.wooledge.org/NullGlob

Gilles Quenot
źródło
1
Zauważ, że tak naprawdę można mieć plik o nazwie *.txt. Warto sprawdzić, czy plik istnieje.
Chris Down,
post odpowiednio zmodyfikowany.
Gilles Quenot
@ChrisDown Pamiętaj, że ten sam komentarz co do twojej odpowiedzi ma tutaj zastosowanie (z potencjalnie bardziej poważnymi konsekwencjami z powodu breakzamiast continue).
Stéphane Chazelas,
6

W bash możesz użyć, shopt -s nullglobaby rozwinąć do pustej tablicy, jeśli nie ma żadnych dopasowań.

W powłokach POSIX bez nullglobtego problemu można uniknąć tego problemu, sprawdzając, czy przekazywana nazwa pliku rzeczywiście istnieje, [ -e "$file" ] || [ -L "$file" ] || continuejako pierwsza część forpętli.

Chris Down
źródło
1
Zauważ, że nie byłby to dokładnie równoważny, ponieważ [ -ezwróciłby wartość false dla niedostępnych plików lub plików, które są dowiązaniami symbolicznymi do niedostępnych lub nieistniejących plików.
Stéphane Chazelas
@StephaneChazelas, pozwól na uznanie punktów dotyczących dowiązań symbolicznych. Ale co masz na myśli przez „niedostępne pliki”? Nawet jeśli chmod 0 the_file, [ -e the_file ]nadal ocenia prawda, więc to musi być coś innego.
dubiousjim
1
przesłano edycję do obsługi zepsutych dowiązań symbolicznych. mam nadzieję, że to w porządku.
dubiousjim
2
@dubiousjim, mkdir -p x/{a,b} && chmod 444 x && echo x/* && [ -e x/a ]. x / a jest niedostępny, ale ponieważ x jest czytelny, x / * będzie się rozwijał.
Stéphane Chazelas,
@StephaneChazelas, świetnie, dziękuję za wyjaśnienie.
dubiousjim,
4

Zwykłą techniką dla pocisków, które nie mają nullglobopcji, jest

set -- [*].type *.type
case $1$2 in
  '[*].type*.type') shift 2;;
  *) shift
esac
for file do
  cmd  -- "$file"
done

Dodatkowym [*].typejest pokrycie przypadku, w którym *.typew bieżącym katalogu znajduje się jeden plik .

Teraz, jeśli chcesz dołączyć pliki kropkowe, staje się to bardziej skomplikowane .

Wierzę, że technika ta została wymyślona przez Laurę Fairhead na usenet kilka lat temu.

Stéphane Chazelas
źródło
0

find . -name '*.type' -maxdepth 0 -exec somecommand "{}" ";"

To forcałkowicie usuwa pętlę i globowanie skorupy z równania. findwykona -execpolecenie raz na mecz, a jeśli nie ma żadnych dopasowań, nigdy nie zostanie wykonane. W -maxdepth 0przesyła zlecenie znaleźć nie rekursja do podkatalogów o nazwie path-argumentu ( .w tym przypadku).

Minusem jest to, że wiąże się z inną aplikacją, choć taką, która jest obecna na praktycznie każdym systemie Linux (i prawdopodobnie także na większości Uniksów).

CVn
źródło