bash find: Verzeichnis der gefundenen Datei abrufen

12

Ich habe einen übergeordneten Ordner mit dem Namen "parent_folder" mit vielen Unterordnern. In diesen Unterordnern befindet sich eine Datei mit dem Namen "foo.mp4".

Ich kann diese Dateien leicht finden, indem ich dies tue:

mymacbook:parent_folder username$ find ./ -name "foo.mp4" -exec echo {} \;

Dies gibt nun den Pfad jeder Datei relativ zu parent_folder / zurück

./path/to/foo.mp4

Wie kann ich nur den Pfad ohne den Dateinamen zurückgeben?

Dubbelj
quelle
1
man find ( ACTIONS ): -printf %h Führende Verzeichnisse des Dateinamens (alle bis auf das letzte Element). Wenn der Dateiname keine Schrägstriche enthält (da er sich im aktuellen Verzeichnis befindet), wird der% h-Bezeichner auf "" erweitert. .
Costas
Können Sie ein Beispiel dafür zeigen? Soll ich das hinter '-exec' oder vorher setzen?
Dubbelj
find ./ -name "foo.mp4" -printf "%h\n"druckt den Pfad für jede gefundene Datei (zeilenweise). Darüber hinaus verwendet wie üblich niemand, -exec echo {}daher gibt es -print(Standard sogar weggelassen) oder printfAktion.
Costas
2
@Costas, -printfist nur GNU. Das OP erwähnt OS / X (ein BSD-System).
Stéphane Chazelas
@ StéphaneChazelas Danke. Ich kannte eine solche Einschränkung für OS / X (BSD) nicht. Arme arme Mac-Benutzer!
Costas

Antworten:

19

Mit GNUfind:

 find . -name foo.mp4 -printf '%h\n'

Bei anderen finds enthalten die angegebenen Verzeichnisnamen keine Zeilenumbrüche:

 find . -name foo.mp4 | sed 's|/[^/]*$||'

Oder:

 find . -name foo.mp4 -exec dirname {} \;

Dies bedeutet jedoch, dass ein dirnameBefehl pro Datei ausgeführt wird.

Wenn Sie dazu einen Befehl ausführen müssen path, können Sie Folgendes tun (Standardsyntax):

 find . -name "featured.mp4" -exec sh -c '
   for file do
     dir=${file%/*}
     ffmpeg -i "$file" -c:v libvpx -b:v 1M -c:a libvorbis "$dir" featured.webm
   done' sh {} +

In diesem Fall können Sie möglicherweise Folgendes verwenden -execdir(eine BSD-Erweiterung, die auch in GNU verfügbar ist find), die sich chdir()im Verzeichnis der Datei befindet:

 find . -name "featured.mp4" -execdir \
   ffmpeg -i {} -c:v libvpx -b:v 1M -c:a libvorbis . featured.webm \;

Beachten Sie jedoch, dass während die GNU-Implementierung von findhier erweitert wird , die BSD- Implementierung {}auf ./filenamehier erweitert wird filename. Hier ist es in Ordnung, da der Dateiname als Argument an eine Option übergeben wird und dies immer featured.mp4ist. Bei anderen Verwendungen müssen Sie jedoch möglicherweise berücksichtigen, dass der Dateiname mit -oder beginnen kann +(und vom Befehl als Option verstanden wird) oder enthält =(und zum Beispiel von awk als variable Zuweisung verstanden werden) oder andere Zeichen, die diese Art von Problem verursachenperl -p/n ( in diesem Fall jedoch nicht alle durch finddas ./Präfix von GNU behoben ) usw., die Sie möglicherweise berücksichtigen müssen .

Stéphane Chazelas
quelle
Wenn Sie sich bewerben find ., haben Sie als Dirname. statt des ganzen Weges.
PersianGulf
Wie würde ich das nun darauf übersetzen? find ./ -name "featured.mp4" -exec ffmpeg -i "{}" -c:v libvpx -b:v 1M -c:a libvorbis [NEED DIRECTORY HERE] featured.webm \; Ich verwende den zweiten Vorschlag, den Sie erwähnt haben.
Dubbelj
@MohsenPahlevanzadeh, das OP hat nicht nach einem absoluten Pfad gefragt, sondern nach dem Namen des Pfads.
Stéphane Chazelas
@ StéphaneChazelas Entschuldigung für die Abstimmung.
PersianGulf
Danke @ StéphaneChazelas. Sie haben mir geholfen, eine ffmpeg-Warteschlange / einen Stapel zu
erstellen
-1

Der folgende Befehl kann auch verwendet werden, um nur die Verzeichnisdetails abzurufen.

find ./ -name "foo.mp4" | rev | cut -d"/" -f2- | rev
Sekar Ramu
quelle
Es scheint etwas übertrieben, drei externe Dienstprogramme aufzurufen, um nur eine Zeichenfolge zu kürzen.
Kusalananda