it-swarm.com.de

So beenden Sie ein Shell-Skript, wenn die Zieldatei nicht vorhanden ist

In Anbetracht des folgenden Skripts möchte ich die Ausführung der Pipeline vermeiden, wenn eine Datei nicht vorhanden ist.

Wie kann ich das Skript sofort beenden, wenn die txt-Datei nicht gefunden wird?

ls */*.txt | grep ab1 | awk '{print $1, $1}' | sed "s/\"/\"\"/g" | xargs -L1 mv
22
amine

Sie können das Vorhandensein von Dateien folgendermaßen überprüfen:

if [[ -f x.txt ]] ; then
    echo file exists.
fi

Verlassen, wenn nicht, so etwas genügt:

if [[ ! -f x.txt ]] ; then
    echo 'File "x.txt" is not there, aborting.'
    exit
fi

Der -f <file> Ist nur einer der vielen Bedingungsausdrücke, die Sie verwenden können. Wenn Sie sich die Manpage bash unter CONDITIONAL EXPRESSIONS Ansehen, werden Sie einen ganzen Host von ihnen sehen.


Wenn Sie (wie in einem Fragenupdate angegeben) überprüfen möchten, ob ein Platzhalter zu Dateien führt, können Sie ihn einfach erweitern und die Fehler beseitigen. Wenn es keine gibt, erhalten Sie eine leere Zeichenfolge, die mit -z Erkannt werden kann:

if [[ -z "$(ls -1 */*.txt 2>/dev/null | grep ab1)" ]] ; then
    echo 'There are no "*/*.txt" files.'
    exit
fi

Beachten Sie, dass ich -1 Verwendet habe, um eine Datei pro Zeile zu erzwingen, obwohl Linux ls dies standardmäßig tut, wenn das Ausgabegerät kein Terminal (aus dem Speicher) ist. Das ist nur für den Fall, dass Sie dies auf einer Maschine versuchen, die in diesem Fall nicht eine pro Zeile erzwingt.


Beachten Sie jedoch, dass die Verwendung von ls und dann awk zum Extrahieren von Spalte 1 nicht zu gut funktioniert, wenn Ihre Dateinamen Leerzeichen enthalten. Die Datei abc ab1.txt Führt beispielsweise dazu, dass nur das abc -Bit extrahiert wird.

Die Verwendung von find mit -print0 In Kombination mit xargs mit -0 Ist die übliche Methode, um Dateien ordnungsgemäß zu verarbeiten, die möglicherweise "Sonderzeichen" enthalten. Es gibt viele andere Optionen, die Sie find geben können, um sicherzustellen, dass nur die erforderlichen Dateien verarbeitet werden, z. B. -maxdepth, Um zu begrenzen, wie weit Sie in der Verzeichnisstruktur nach unten gehen, und -name. um Dateinamen richtig zu filtern.

Wenn Sie jedoch wissen dass Sie diese Art von Dateien nie haben werden, ist es wahrscheinlich in Ordnung, die ls -Lösung zu verwenden, stellen Sie einfach sicher, dass Sie mit ihren Mängeln vertraut sind.

40
paxdiablo

Benutze test

Eine schnelle und kurze Möglichkeit, die Existenz zu testen:

test -e $FILENAME || exit

Sie können es verketten, indem Sie Folgendes tun:

test -e $FILENAME && something | something-else 

In diesem Fall werden something und something-else Nur ausgeführt, wenn die Datei existiert.

Beispielsweise:

➤ test -e ~/.bashrc && echo True || echo False
True
➤ test -e ./exists-not && echo True || echo False
False

Nebenbei: Beachten Sie, dass [ Ein Alias ​​für test ist. Die Semantik von [[ Wird durch bash definiert und kann gefunden werden auf der bash-Manpage

Jedoch...

... Sie sind wahrscheinlich besser dran, wenn Sie find verwenden, um Ihre Dateien zu erhalten:

find ./ -maxdepth 2 -name "*ab1*.txt" -exec do-something-to-filename '{}' \;

Da die Ausgabe von ls nicht zuverlässig analysiert werden kann. Dadurch wird auch nur dann der Befehl do-something-to-filename Ausgeführt, wenn der Dateiname vorhanden ist.

{} Wird bei jedem Aufruf von do-something-to-filename Durch den Dateinamen ersetzt.

9
brice

Ich habe es versucht und das hat bei mir funktioniert

test -s <<your file path>> && exit 0 || <<things to do when file NOT exists>>

Beachten Sie, dass ich tatsächlich beendet werde, wenn die Datei nicht vorhanden ist

0
Kishan B

find ... -exec ... Oder find ... -print0 | xargs -0 ... Ist im Allgemeinen in Ordnung, aber Sie können dies direkt mit einem Glob tun, indem Sie die nullglob -Option von bash verwenden:

bash-3.2$ echo *foo
*foo
bash-3.2$ shopt -s nullglob
bash-3.2$ echo *foo

bash-3.2$ 

Abhängig vom Rest Ihres Skripts können Sie dies mit shopt -u nullglob Rückgängig machen oder auch nicht.

0
Kevin