Ich dachte, das wäre einfach - aber es erweist sich als komplexer als ich erwartet hatte.
Ich möchte alle Dateien eines bestimmten Typs in einem Verzeichnis durchlaufen, also schreibe ich Folgendes:
#!/bin/bash
for fname in *.zip ; do
echo current file is ${fname}
done
Dies funktioniert , solange sich mindestens eine passende Datei im Verzeichnis befindet. Wenn es jedoch keine passenden Dateien gibt, erhalte ich Folgendes:
current file is *.zip
Ich habe dann versucht:
#!/bin/bash
FILES=`ls *.zip`
for fname in "${FILES}" ; do
echo current file is ${fname}
done
Während der Körper der Schleife nicht ausgeführt wird, wenn keine Dateien vorhanden sind, erhalte ich eine Fehlermeldung von ls:
ls: *.zip: No such file or directory
Wie schreibe ich eine Schleife, die keine übereinstimmenden Dateien sauber verarbeitet?
shopt -s nullglob
vor dem Ausführen der for-Schleife hinzu.FILES=
ls * .zip; for fname in "${FILES}"...
aber es funktioniert wie erwartetfor fname in *.zip ; do....
for file in *.zip
nicht`ls ...`
. @ cuonglms Vorschlag ist, dass er*.zip
sich zu nichts erweitert, wenn das Muster keiner Datei entspricht.ls
ohne Argumente listet das aktuelle Verzeichnis auf.ls
im Allgemeinen vermieden werden sollte: Warum nicht analysierenls
? ; Siehe auch den Link oben auf dieser Seite zum Artikel ParsingLs von BashGuide .Antworten:
In
bash
können Sie dienullglob
Option so einstellen , dass ein Muster, das mit nichts übereinstimmt, "verschwindet", anstatt als Literalzeichenfolge behandelt zu werden:Im POSIX-Shell-Skript müssen Sie nur überprüfen, ob es
fname
existiert (und gleichzeitig mit[ -f ]
prüfen, ob es sich um eine reguläre Datei (oder einen Symlink zu einer regulären Datei) handelt und nicht um andere Typen wie das Verzeichnis / fifo / device ...):Ersetzen Sie
[ -f "$fname" ]
durch,[ -e "$fname" ] || [ -L "$fname ]
wenn Sie alle (nicht ausgeblendeten) Dateien durchlaufen möchten, deren Name.zip
unabhängig vom Typ auf endet .Ersetzen Sie
*.zip
durch,.*.zip .zip *.zip
wenn Sie auch versteckte Dateien berücksichtigen möchten, deren Name auf endet.zip
.quelle
shopt -s nullglob
hat bei mir unter Ubuntu 17.04 nicht funktioniert, hat aber[ -f "$fname" ] || continue
gut funktioniert.bash
.In einem Kommentar erwähnen Sie hier das Aufrufen einer Funktion ...
quelle
Verwenden Sie find
Sie MÜSSEN Ihre Shell-Funktion mit exportieren,
export -f
damit dies funktioniert. Jetzt wirdfind
ausgeführt,bash
wodurch Ihre Shell-Funktion ausgeführt wird, und es wird nur die aktuelle Verzeichnisebene beibehalten.quelle
Anstatt:
Versuchen:
Wenn ls fehlschlägt (was in Ihrem Fall der Fall ist), wird die fehlgeschlagene Ausgabe überprüft und als leere Variable zurückgegeben.
Sie können dem eine Logik hinzufügen, damit es "No File Found" zurückgibt.
Auf diese Weise wird, wenn der vorherige Befehl erfolgreich war (mit einem Wert von 0 beendet), die aktuelle Datei gedruckt, andernfalls wird "Keine Dateien gefunden" gedruckt.
quelle
grep
), anstatt zu versuchen, das Problem mit einem besseren Tool zu beheben (find
) oder die relevante Einstellung für die aktuelle Lösung zu ändern (mitshopt -s nullglob
)shopt -s nullglob
funktioniert das nicht. Ich habe es versucht,find
während ich meine Antwort überprüft habe. Ich denke wegen der Exportsache, die Dani gesagt hat.