bash find: récupère le répertoire du fichier trouvé


12

J'ai un dossier parent nommé "parent_folder" avec beaucoup de sous-dossiers, dans ces sous-dossiers se trouve un fichier nommé "foo.mp4".

Je peux trouver ces fichiers facilement en faisant ceci:

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

Maintenant, cela renvoie le chemin de chaque fichier, par rapport à parent_folder /

./path/to/foo.mp4

Comment puis-je retourner uniquement le chemin, sans le nom de fichier?


1
man find ( ACTIONS ): -printf %h principaux répertoires du nom du fichier (tous sauf le dernier élément). Si le nom de fichier ne contient aucune barre oblique (car il se trouve dans le répertoire en cours), le spécificateur% h se développe en "." .
Costas

Pourriez-vous en montrer un exemple? Dois-je mettre cela derrière «-exec» ou avant?
dubbelj

find ./ -name "foo.mp4" -printf "%h\n"affichera le chemin d'accès à chaque fichier trouvé (un par ligne). De plus, comme d'habitude, personne n'utilise -exec echo {}donc il y a -print(défaut même omis) ou printfaction.
Costas

2
@Costas, -printfest uniquement GNU. L'OP mentionne OS / X (un système BSD).
Stéphane Chazelas

@ StéphaneChazelas Merci. Je ne connaissais pas une telle limitation pour OS / X (BSD). Pauvres pauvres utilisateurs de mac!
Costas

Réponses:


20

Avec GNUfind:

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

Avec les autres finds, les noms de répertoire fournis ne contiennent pas de caractères de nouvelle ligne:

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

Ou:

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

bien que cela signifie exécuter une dirnamecommande par fichier.

Si vous devez exécuter une commande à ce sujet path, vous pouvez le faire (syntaxe standard):

 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 {} +

Bien que dans ce cas, vous puissiez utiliser -execdir(une extension BSD également disponible dans GNU find), qui se trouve chdir()dans le répertoire du fichier:

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

Attention cependant, bien que l'implémentation GNU de finds'étende {}jusqu'à ./filenameici, celles de BSD s'étendent jusqu'à filename. C'est OK ici car le nom de fichier est passé comme argument à une option et est toujours de featured.mp4toute façon, mais pour d'autres utilisations, vous devrez peut-être tenir compte du fait que le nom de fichier peut commencer par -ou +(et être compris comme une option par la commande) ou contenir =(et être compris comme une affectation de variable par awk par exemple), ou d'autres caractères causant ce genre de problèmeperl -p/n (mais pas tous corrigés par findle ./préfixe de GNU dans ce cas), etc., dont vous devrez peut-être tenir compte .


Lorsque vous postulez find ., vous aurez comme dirname. au lieu du chemin entier.
PersianGulf

Maintenant, comment pourrais-je traduire cela en ceci? find ./ -name "featured.mp4" -exec ffmpeg -i "{}" -c:v libvpx -b:v 1M -c:a libvorbis [NEED DIRECTORY HERE] featured.webm \; J'utilise la deuxième suggestion que vous avez mentionnée.
dubbelj

@MohsenPahlevanzadeh, l'OP n'a pas demandé de chemin absolu, mais le nom de dir du chemin.
Stéphane Chazelas

@ StéphaneChazelas Désolé pour voter contre.
PersianGulf

Merci @ StéphaneChazelas. Vous m'avez aidé à faire une file d'attente / batch ffmpeg
dubbelj

-1

La commande ci-dessous peut également être utilisée pour récupérer uniquement les détails du répertoire.

find ./ -name "foo.mp4" | rev | cut -d"/" -f2- | rev

Il semble un peu excessif d'appeler trois utilitaires externes juste pour couper une chaîne.
Kusalananda
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.