Vermeidung von Fehlern aufgrund eines nicht erweiterten Sternchens

16

In der Bash verwende ich oft for-Schleifen wie die folgenden

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

um eine Operation für alle passenden Dateien durchzuführen *.type. Wenn in den Arbeitsverzeichnissen keine Datei mit dieser Endung gefunden wird, wird der Stern nicht erweitert und normalerweise erhalte ich eine Fehlermeldung, dass die Datei nicht gefunden wurde. Ich kann mir sofort mehrere Möglichkeiten vorstellen, um diesen Fehler zu vermeiden. Das Hinzufügen einer Bedingung scheint jedoch nicht sehr elegant zu sein. Gibt es einen kurzen und sauberen Weg, um dies zu erreichen?

highsciguy
quelle

Antworten:

20

Ja, führen Sie den folgenden Befehl aus:

shopt -s nullglob

es wird die Übereinstimmung annullieren und kein Fehler wird ausgelöst.

  • Wenn Sie dieses Verhalten standardmäßig möchten, fügen Sie den Befehl in Ihrem ~/.bashrc
  • Wenn Sie ein Null-Glob in der POSIX-Shell erkennen möchten, versuchen Sie es

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

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

Gilles Quenot
quelle
1
Beachten Sie, dass es tatsächlich möglich ist, eine Datei aufrufen zu lassen *.txt. Es lohnt sich zu prüfen, ob die Datei existiert.
Chris Down
Beitrag entsprechend bearbeitet.
Gilles Quenot
@ChrisDown Beachten Sie, dass hier derselbe Kommentar wie in Ihrer Antwort gilt (mit möglicherweise schwerwiegenderen Konsequenzen aufgrund von breakanstelle von continue).
Stéphane Chazelas
6

In bash können Sie es verwenden shopt -s nullglob, um ein leeres Array zu erstellen, wenn keine Übereinstimmungen vorliegen.

In POSIX-Shells ohne nullglobkönnen Sie dieses Problem vermeiden, indem Sie überprüfen, ob der übergebene Dateiname tatsächlich vorhanden ist, indem Sie [ -e "$file" ] || [ -L "$file" ] || continueals ersten Teil Ihrer forSchleife angeben.

Chris Down
quelle
1
Beachten Sie, dass dies nicht unbedingt äquivalent [ -ewäre, da dies bei nicht zugreifbaren Dateien oder bei Dateien, die symbolisch mit nicht zugreifbaren oder nicht vorhandenen Dateien verknüpft sind, den Wert false zurückgibt.
Stéphane Chazelas
@StephaneChazelas, lass die Punkte über Symlinks anerkannt werden. Aber was halten Sie von "unzugänglichen Dateien"? Auch wenn ich chmod 0 the_file, [ -e the_file ]wertet immer noch wahr, so ist es etwas anderes sein muss.
dubiousjim
1
übermittelte Bearbeitung, um defekte Symlinks zu behandeln. hoffe das ist ok
dubiousjim
2
@dubiousjim, mkdir -p x/{a,b} && chmod 444 x && echo x/* && [ -e x/a ]. x / a ist nicht zugänglich, aber da x lesbar ist, wird x / * erweitert.
Stéphane Chazelas
@StephaneChazelas, toll, danke für die Erklärung.
dubiousjim
4

Die übliche Technik für Muscheln, die keine nullglobOption haben, ist

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

Das Besondere [*].typeist, den Fall abzudecken, *.typein dem im aktuellen Verzeichnis eine Datei aufgerufen wird .

Wenn Sie nun Punktdateien einbinden möchten , wird dies komplizierter .

Ich glaube, diese Technik wurde vor ein paar Jahren von Laura Fairhead am Usenet geprägt.

Stéphane Chazelas
quelle
0

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

Dadurch werden die forSchleife und das Globen der Shell vollständig aus der Gleichung entfernt. findführt den -execBefehl einmal pro Match aus, und wenn es keine Matches gibt, wird er niemals ausgeführt. Die -maxdepth 0Instruktionen finden, dass sie nicht in Unterverzeichnisse des genannten path-Arguments ( .in diesem Fall) zurückkehren.

Der Nachteil ist, dass es sich um eine andere Anwendung handelt, die jedoch auf praktisch jedem Linux-System (und wahrscheinlich auch auf den meisten Unix-Systemen) vorhanden ist.

ein CVn
quelle