find: nichts tun, wenn keine Dateien angegeben werden

find: nichts tun, wenn keine Dateien angegeben werden

Ich möchte use findfür einige Dateinamen aufrufen.

find $(do_something to find filenames) -print0 | xargs -r0 ls -ld

Dies bricht ab, wenn $(do_something to find filenames)nichts zurückgegeben wird: Der Find-Befehl beginnt mit der rekursiven Suche.

Gibt es eine Möglichkeit, find anzuweisen, nichts zu tun, wenn es keinen expliziten Dateinamen/Verzeichnisnamen als Argument erhält?

Antwort1

Mit zshwürde ich Folgendes tun:

files=($(do_something to find filenames))
(($#files)) && find $files ...

Mit tcsh:

set files=(`do_something to find filenames`)
if ($#files) find $files:q ...

Mit bashoder ,mkshksh93

set -f; files=($(do_something to find filenames))
((${#files[@]})) && find "${files[@]}" ...

POSIX:

set -f; set -- $(do_something to find filenames)
[ "$#" -gt 0 ] && find "$@" ...

(in Bash und anderen POSIX-Shells $(...)werden Splits ( $IFSstandardmäßig bei Leerzeichen, Tabulator und Zeilenumbruch) durchgeführt, aber es wird auch Globbing auf die resultierenden Wörter angewendet, was Sie hier wahrscheinlich nicht wollen, daher das set -f. Andere Shells ((t)csh, zsh, fish, rc, es...) haben dieses Problem nicht).

Antwort2

Wie wäre es damit:

paths=$(do_something to find filenames)
if [ "$paths" ]; then
    find "$paths" ...
fi

Dies funktioniert unabhängig von der findImplementierung.

Beachten Sie, dass find "$paths"mehr als ein Pfadname Probleme verursacht. Wenn die Pfadnamen keine Leerzeichen enthalten, können Sie Folgendes verwenden: find $paths, andernfalls ist diese Funktion eine funktionierende Alternative:

dofind() {
    set -f
    set -- $(do_something to find filenames)
    if [ $# -gt 0 ]; then
        find "$@" ...
    fi
    set +f
}

Es deaktiviert das Dateiglobbing und verwendet es dann, set --um den Shell-Argumentvektor festzulegen. Dies funktioniert mit jeder POSIX-Shell.

Antwort3

Sie können findzum Starten ein zusätzliches, nicht vorhandenes Verzeichnis angeben:

find " " $(do_something to find filenames) -print0 | xargs -r0 ls -ld

Um das zu bereinigen, löschen Sie finddie Fehlerausgabe:

find " " $(do_something to find filenames) -print0 2>/dev/null | xargs -r0 ls -ld

(dann merkt man es aber nicht, wenn wieder ein Fehler auftritt...).

Wenn do_something to find filenamesDateinamen ausgegeben werden, findwird dies bemängelt " ", aber der Rest der Befehlszeile wird trotzdem verarbeitet. Wenn keine Dateinamen ausgegeben werden, findwird dies erneut bemängelt, " "aber der Standardwert wird nicht hinzugefügt ..

Antwort4

In zsh(und den meisten nicht von Bourne abgeleiteten Shells) gilt: Wenn ein (oderalleabhängig von der Schale)Globusnicht erweitert wird, wird der Befehl abgebrochen.

$(do_something to find filenames)ist kein Glob, aber Sie können es zu einem machen, indem Sie in Folgendes einen Glob-Qualifizierer anhängen zsh:

 find $(do_something to find filenames)(#q) -print0...

Oben (#q)wird das (ein leerer Glob-Qualifizierer, der also sonst nichts bewirkt) an das letzte Wort angehängt, das sich aus der Aufteilung der Ausgabe von ergibt do_something to find filenames, sodass der Befehl abgebrochen wird, wenn dieser Befehl keine (oder eine leere) Ausgabe erzeugt, aber auch, wenn dieses letzte Wort (und nur dieses letzte Wort) nicht in einen vorhandenen Pfad aufgelöst wird. Sie können es auf jedes Wort anwenden lassen, das sich aus dieser Aufteilung ergibt (sodass der Befehl abgebrochen wird, wenn eines dieser Wörter nicht in eine vorhandene Datei aufgelöst wird), und zwar mit:

 find ${^$(do_something to find filenames)}(#q) -print0...

verwandte Informationen