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?

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


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.


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.


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).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.