75 votes

Trouver les répertoires qui ne contiennent pas de fichier

Oui, je fais le tri dans ma musique. J'ai tout arrangé magnifiquement dans le mantra suivant : /Artist/Album/Track - Artist - Title.ext et s'il y en a une, la couverture se trouve en /Artist/Album/cover.(jpg|png) .

Je veux parcourir tous les répertoires de second niveau et trouver ceux qui n'ont pas de couverture. Par second niveau, je veux dire que je ne me soucie pas de savoir si /Britney Spears/ n'a pas de cover.jpg, mais je me soucierais si /Britney Spears/In The Zone/ n'en avait pas.

Ne vous préoccupez pas du téléchargement de la couverture (c'est un projet amusant pour moi demain), je ne m'intéresse qu'à l'aspect glorieux de l'histoire d'une sorte d'inverse. find exemple.

98voto

phoibos Points 19941

Cas 1 : vous connaissez le nom exact du fichier à rechercher

Utilisez find con test -e your_file pour vérifier si un fichier existe. Par exemple, vous cherchez les répertoires qui n'ont pas de cover.jpg en eux :

find base_dir -mindepth 2 -maxdepth 2 -type d '!' -exec test -e "{}/cover.jpg" ';' -print

C'est sensible à la casse.

Cas 2 : Vous voulez être plus flexible

Vous n'êtes pas sûr de l'affaire, et l'extension pourrait être jPg , png ...

find base_dir -mindepth 2 -maxdepth 2 -type d '!' -exec sh -c 'ls -1 "{}"|egrep -i -q "^cover\.(jpg|png)$"' ';' -print

Explication :

  • Vous devez créer un Shell. sh pour chaque répertoire, car le piping n'est pas possible lorsque l'on utilise find
  • ls -1 "{}" produit uniquement les noms de fichiers du répertoire find traverse actuellement
  • egrep (au lieu de grep ) utilise des expressions régulières étendues ; -i rend la recherche insensible à la casse, -q permet d'omettre toute sortie
  • "^cover\.(jpg|png)$" est le modèle de recherche. Dans cet exemple, il correspond à e.g. cOver.png , Cover.JPG o cover.png . Le site . doit être échappé sinon cela signifie qu'il correspond à tout caractère. ^ marque le début de la ligne, $ sa fin

Autres exemples de modèles de recherche pour egrep :

Remplacer le egrep -i -q "^cover\.(jpg|png)$" partie avec :

  • egrep -i -q "cover\.(jpg|png)$" : Correspond aussi cd_cover.png , album_cover.JPG ...
  • egrep -q "^cover\.(jpg|png)$" : Correspondances cover.png , cover.jpg mais PAS Cover.jpg (la sensibilité à la casse n'est pas désactivée)
  • egrep -iq "^(cover|front)\.jpg$" : correspond par exemple front.jpg , Cover.JPG mais no Cover.PNG

Pour plus d'informations à ce sujet, consultez le site Expressions régulières .

13voto

Mufaka Points 54

Simple, il s'avère. Ce qui suit obtient une liste des répertoires avec la couverture et la compare avec une liste de tous les répertoires de second niveau. Les lignes qui apparaissent dans les deux "fichiers" sont supprimées, laissant une liste de répertoires qui ont besoin de couvertures.

comm -3 \
    <(find ~/Music/ -iname 'cover.*' -printf '%h\n' | sort -u) \
    <(find ~/Music/ -maxdepth 2 -mindepth 2 -type d | sort) \
| sed 's/^.*Music\///'

Hourra.

Notes :

  • comm Les arguments de l'entreprise sont les suivants :

    • -1 supprimer les lignes uniques au fichier1
    • -2 supprimer les lignes uniques au fichier2
    • -3 supprimer les lignes qui apparaissent dans les deux fichiers
  • comm ne prend que des fichiers, d'où le <(...) méthode d'entrée. Le contenu est acheminé par un véritable fichier [temporaire].

  • comm a besoin d'une entrée triée, sinon elle ne fonctionne pas et find ne garantit en aucun cas une commande. Il faut aussi qu'elle soit unique. La première find a pu trouver plusieurs fichiers pour cover.* donc il pourrait y avoir des entrées en double. sort -u les réduit rapidement à un seul. La deuxième trouvaille sera toujours unique.

  • dirname est un outil pratique pour obtenir le répertoire d'un fichier sans avoir recours à sed (et al).

  • find y comm sont tous deux un peu désordonnés avec leur sortie. La finale sed est là pour nettoyer les choses afin que vous vous retrouviez avec Artist/Album . Cela peut être souhaitable ou non pour vous.

9voto

Humphrey Bogart Points 2270

Ce problème est beaucoup plus facile à résoudre avec globbing qu'avec find.

$ cd ... # to the directory one level above the album/artist structure

$ echo */*/*.cover   # lists all the covers

$ printf "%s\n" */*/*.cover # lists all the covers, one per line

Supposons maintenant que vous n'ayez pas de fichiers errants dans cette belle structure. Le répertoire actuel ne contient que des sous-répertoires d'artistes, et ceux-ci ne contiennent que des sous-répertoires d'albums. Nous pouvons alors faire quelque chose comme ceci :

$ diff  <(for x in */*/cover.jpg; do echo "$(dirname "$x")" ; done) <(printf "%s\n" */*)

El <(...) La syntaxe est la substitution du processus de Bash : elle vous permet d'utiliser une commande à la place d'un argument de fichier. Elle vous permet de traiter la sortie d'une commande comme un fichier. Ainsi, nous pouvons exécuter deux programmes, et prendre leur différence, sans sauvegarder leur sortie dans des fichiers temporaires. Le site diff Le programme pense qu'il travaille avec deux fichiers, mais en fait il lit à partir de deux tuyaux.

La commande qui produit l'entrée droite de diff , printf "%s\n" */* ne liste que les répertoires d'albums. La commande de gauche parcourt les répertoires *.cover et imprime leurs noms de répertoire.

Test de fonctionnement :

$ find .   # let's see what we have here
.
./a
./a/b
./foo
./foo/bar
./foo/baz
./foo/baz/cover.jpg

$ diff  <(for x in */*/cover.jpg; do echo "$(dirname "$x")" ; done) <(printf "%s\n" */*)
0a1,2
> a/b
> foo/bar

Aha, le a/b y foo/bar n'ont pas de cover.jpg .

Il y a quelques cas de coin cassé, comme celui par défaut * s'étend à lui-même s'il ne correspond à rien. Ce problème peut être résolu avec la fonction set -o nullglob .

1voto

Roel Van de Paar Points 555
ls --color=never */*.txt | sed 's|/.*||' | sort -u -n > withtxt.txt
ls --color=never -d * | sort -u -n > all.txt
diff all.txt withtxt.txt

Affiche tous les répertoires qui ne contiennent pas de fichiers txt.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X