Suchaktion funktioniert bei bestimmter Suche nicht

Suchaktion funktioniert bei bestimmter Suche nicht

Ich versuche, mit dem findBefehl die Größe einer bestimmten Gruppe von Dateien aufzulisten, erhalte aber keine Ausgabe. Der von mir verwendete Befehl lautet:

find POD -type f -name *.mp3 -or -name *.ogg -ls

Das erzeugt keine Ausgabe. Während:

find POD -type f -name *.mp3 -or -name *.ogg

erzeugt eine Ausgabe, ich habe auch die folgenden Aktionen ausprobiert:

-printf "%p %k KB\n"
-exec ls -ls '{}' \;
-print0

aber alle diese Aktionen geben keine Ausgabe aus. Wenn ich eine dieser Aktionen mit einem anderen Ausdruck verwende, z. B.:

find . -maxdepth 1 -type f -printf "%p %k KB\n"

Ich bekomme auch die erwartete Ausgabe. Hat jemand eine Idee, wo das Problem liegt? Ich verwende:

Linux irimi 3.10.37-1-MANJARO #1 SMP Mon Apr 14 20:56:29 UTC 2014 x86_64 GNU/Linux

auch bekannt als eine aktuelle Manjaro-Linux-Distribution. Die Shell, die ich verwende, ist: /bin/bashVersion 4.3.8(1)-release.

Der Inhalt meiner SHELLOPTSUmgebungsvariable ist:

braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor

meine BASHOPTSUmgebungsvariable ist:

cdspell:checkwinsize:cmdhist:complete_fullquote:dotglob:expand_aliases:extglob:extquote:force_fignore:histappend:hostcomplete:interactive_comments:nocaseglob:progcomp:promptvars:sourcepath

Auch hier wäre ich für jede Hilfe beim Debuggen sehr dankbar.

Antwort1

Es gibt eine Falle mit demund/oderSchlüsselwörter auf find. orwerden auf alle folgenden Parameter angewendet, einschließlich der Aktion ( -lsin Ihrem Beispiel). andAusdrücke ohne or(oder mit and) werden in Lesereihenfolge ausgewertet, mit einem letzten Stopp als „false“. Es gibt kein implicit ().

Der Befehl find POD -type f -name *.mp3 -or -name *.ogg -lsbedeutet also:

  • Suche (ausgehend vom POD-Verzeichnis) nach Dateien --- wenn keine Datei gefunden: STOP
  • sonst (Datei gefunden) Musterübereinstimmung prüfen *.mp3 --- wenn Musterübereinstimmung: STOP ! (weil ORab hier angewendet und nur, wenn der vorherige Befehl fehlgeschlagen ist (aber nur der vorherige Befehl, nicht die vorherigen Befehlsgruppen)

und weil Sie in der Befehlszeile eine Execute-Anweisung (,, ....) hinzufügen, gibt es keinen impliziten Befehl -lsund daher nichts auszuführen, wenn 1) alle Bedingungen von 1) erfüllt sind (Datei und Muster übereinstimmen). Wenn Sie das Letzte entfernen, gibt es am Ende jeder Bedingung eine implizite Verzweigung.-exec-print-print-ls-print

  • andernfalls, wenn das Muster nicht übereinstimmt, nach allem (Datei/Verzeichnis) suchen, das dem Muster entspricht, *.oggund es auflisten (das -lsist kein Bedingungsbefehl, er wird nur ausgeführt, wenn der vorherige Befehl/Test „Muster“ *.oggwahr ist). Aber wegen 1), 2) wird nur für NICHT-MP3-Dateien ausgewertet. Wenn Sie keine .oggDateien haben, sehen Sie nichts.

Lösung 1 Wiederholen Sie den Ausführungsbefehl in jedem logischen Zweig

   find POD -type f -name "*.mp3" -ls -or -name "*.ogg" -ls

Lösung 2(Shell-geschützte) Klammer hinzufügen

   find POD -type f \( -name "*.mp3" -ls -or -name "*.ogg" \) -ls

Notiz Sie sollten die Muster schützen, um eine Shell-Musterauswertung im aktuellen Verzeichnis zu vermeiden.

Antwort2

Ich denke, es liegt an der Auswertungsreihenfolge (Fehlen einer expliziten Priorität), z. B. wenn

-name '*.mp3' -o -name '*.ogg' -ls

Wenn dann -name '*.ogg'„false“ ausgewertet wird, lswird die Aktion nicht ausgeführt. Sie können das erwartete Verhalten erzielen, indem Sie Ihre OR-Ausdrücke in Klammern gruppieren – zum Beispiel, wenn

$ ls tests
file1.mp3  file2.mp3  file3.mp3

Dann

$ find tests \( -name '*.mp3' -o -name '*.ogg' \) -print
tests/file3.mp3
tests/file1.mp3
tests/file2.mp3

wohingegen

$ find tests -name '*.mp3' -o -name '*.ogg' -print

erzeugt keine Ausgabe. Beachten Sie, dass

$ find tests -name '*.mp3' -o -name '*.ogg'

ist ein Sonderfall, da er implizit behandelt wird als

$ find tests \( -name '*.mp3' -o -name '*.ogg' \) -print

Beachten Sie auch, dass es empfehlenswert ist, Shell-Globs in einem findBefehl in Anführungszeichen zu setzen oder zu maskieren, um zu verhindern, dass die Shell sie erweitert – siehe den NON-BUGSAbschnitt auf der Manpage „Find“.

verwandte Informationen