Oui, je trie ma musique. J'ai tout arrangé magnifiquement dans le mantra suivant: /Artist/Album/Track - Artist - Title.ext
et s'il en existe une, la couverture reste en place /Artist/Album/cover.(jpg|png)
.
Je veux parcourir tous les répertoires de deuxième niveau et trouver ceux qui n'ont pas de couverture. Au deuxième niveau, je veux dire que je ne me soucie pas de /Britney Spears/
ne pas avoir de cover.jpg, mais je me soucierais de /Britney Spears/In The Zone/
ne pas en avoir.
Ne vous inquiétez pas du téléchargement de la couverture (c'est un projet amusant pour moi demain). Je ne me soucie que de la glorieuse bash-fuiness d'un find
exemple inverse .
Réponses:
Cas 1: Vous connaissez le nom de fichier exact à rechercher
Utilisez
find
avectest -e your_file
pour vérifier si un fichier existe. Par exemple, vous recherchez des répertoires qui n'en contiennent pascover.jpg
:C'est sensible à la casse cependant.
Cas 2: Vous voulez être plus flexible
Vous n'êtes pas sûr du cas, et l'extension pourrait être
jPg
,png
...Explication:
sh
pour chaque répertoire car la tuyauterie n’est pas possible avecfind
ls -1 "{}"
sort seulement les noms de fichiers du répertoirefind
qui traverse actuellementegrep
(au lieu degrep
) utilise des expressions régulières étendues;-i
rend la recherche insensible à la casse,-q
fait en sorte qu'elle omette toute sortie"^cover\.(jpg|png)$"
est le motif de recherche. Dans cet exemple, cela correspond par exemple àcOver.png
,Cover.JPG
oucover.png
. Le.
doit être échappé sinon cela signifie qu'il correspond à n'importe quel caractère.^
marque le début de la ligne,$
sa finAutres exemples de motif de recherche pour egrep :
Remplacez la
egrep -i -q "^cover\.(jpg|png)$"
partie par:egrep -i -q "cover\.(jpg|png)$"
: Correspond aussicd_cover.png
,album_cover.JPG
...egrep -q "^cover\.(jpg|png)$"
: Correspondcover.png
,cover.jpg
mais PASCover.jpg
(la sensibilité à la casse n'est pas désactivée)egrep -iq "^(cover|front)\.jpg$"
: correspond par exemplefront.jpg
,Cover.JPG
mais pasCover.PNG
Pour plus d'informations à ce sujet, consultez Expressions régulières .
la source
test
.-exec bash -c '[[ -n $(find "{}" -iname "cover.*") ]]' \;
mais c'est assez dégoûtant en termes d'optimisation. Cela fonctionne cependant.test
une charge de-o EXPRESSION
requêtes OR, par exemple ...test -e "{}/cover.jpg" -o -e "{}/cover.png"
ce qui est mieux que de faire une recherche complète mais reste sensible à la casse.$
nom de répertoire (Ke $ ha, par exemple).Simple, ça se passe. Ce qui suit obtient une liste de répertoires avec la couverture et la compare à une liste de tous les répertoires de second niveau. Les lignes qui apparaissent dans les deux "fichiers" sont supprimées, ce qui laisse une liste de répertoires à couvrir.
Hourra.
Remarques:
comm
Les arguments de sont les suivants:-1
supprimer les lignes uniques à file1-2
supprimer les lignes uniques à file2-3
supprimer les lignes qui apparaissent dans les deux fichierscomm
ne prend que des fichiers, d’où la<(...)
méthode de saisie fantaisiste . Cela dirige le contenu via un fichier réel [temporaire].comm
a besoin d'entrées triées ou cela ne fonctionne pas etfind
ne garantit en aucun cas une commande. Il doit également être unique. La premièrefind
opération pourrait rechercher plusieurs fichierscover.*
afin d'éviter des doublons.sort -u
rapidement les remue à un. La deuxième découverte sera toujours unique.dirname
est un outil pratique pour obtenir le répertoire d'un fichier sans avoir recours àsed
(et al).find
etcomm
sont tous les deux un peu en désordre avec leur sortie. La finalesed
est là pour nettoyer les choses afin que vous restiez avecArtist/Album
. Cela peut ou peut ne pas être souhaitable pour vous.la source
find
peut éventuellement être simplifiéfind ~/Music/ -iname 'cover.*' -printf '%h\n'
, en évitant le besoindirname
. maisdirname
est pratique ailleurs.C'est beaucoup plus agréable à résoudre avec Globbing qu'avec Find.
Supposons maintenant que vous n’ayez pas de fichiers parasites 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. Ensuite, nous pouvons faire quelque chose comme ceci:
La
<(...)
syntaxe est la substitution de processus Bash: elle vous permet d'utiliser une commande à la place d'un argument de fichier. Il vous permet de traiter la sortie d'une commande en tant que fichier. Nous pouvons donc exécuter deux programmes et prendre leurs diff, sans enregistrer leur sortie dans des fichiers temporaires. Lediff
programme pense travailler avec deux fichiers, mais en réalité, il lit deux canaux.La commande qui produit l'entrée de droite dans
diff
,printf "%s\n" */*
répertorie simplement les répertoires de l'album. La commande de gauche effectue une itération dans les*.cover
chemins et affiche leurs noms de répertoire.Essai:
Aha, les répertoires
a/b
etfoo/bar
ont pascover.jpg
.Il y a des cas de coins cassés, comme celui qui par défaut se
*
développe s'il ne correspond à rien. Ceci peut être résolu avec Bash'sset -o nullglob
.la source
comm
plus propres quediff
?comm -3 <(printf "%s\n" */*/cover* | sed -r 's/\/[^\/]+$//' | sort -u) <(printf "%s\n" */*)
semble être un compromis raisonnable sans aucundiff
fluff. Il est cependant un peu plus lent que ma double trouvaille.Affiche tous les répertoires ne contenant pas de fichiers txt.
la source