Ja, ich sortiere meine Musik. Ich habe alles in dem folgenden Mantra wunderschön arrangiert: /Artist/Album/Track - Artist - Title.ext
und wenn es eines gibt, sitzt das Cover darin /Artist/Album/cover.(jpg|png)
.
Ich möchte alle Verzeichnisse der zweiten Ebene durchsuchen und diejenigen finden, die kein Cover haben. Mit der zweiten Ebene meine ich, es ist mir egal, ob /Britney Spears/
es keine cover.jpg gibt, aber es wäre mir wichtig, wenn /Britney Spears/In The Zone/
es keine gäbe .
Mach dir keine Sorgen über das Herunterladen des Covers (das ist ein lustiges Projekt für mich von morgen). Mir geht es nur um die glorreiche Schüchternheit eines inversen find
Beispiels.
Antworten:
Fall 1: Sie kennen den genauen Dateinamen, nach dem Sie suchen müssen
Verwenden Sie
find
mittest -e your_file
überprüfen , ob eine Datei vorhanden ist . Zum Beispiel suchen Sie nach Verzeichnissen, die keine enthaltencover.jpg
:Es ist jedoch case sensitive.
Fall 2: Sie möchten flexibler sein
Sie sind sich nicht sicher, und die Erweiterung könnte sein
jPg
,png
...Erläuterung:
sh
für jedes Verzeichnis eine Shell erzeugen, da bei der Verwendung kein Piping möglich istfind
ls -1 "{}"
gibt nur den Dateinamen des Verzeichnisses aus,find
das gerade durchsucht wirdegrep
(anstelle vongrep
) verwendet erweiterte reguläre Ausdrücke;-i
Macht die Suche unabhängig von Groß- und Kleinschreibung,-q
lässt keine Ausgabe zu"^cover\.(jpg|png)$"
ist das Suchmuster. In diesem Beispiel entspricht es zum BeispielcOver.png
,Cover.JPG
odercover.png
. Das.
muss maskiert werden, sonst bedeutet es, dass es mit einem beliebigen Zeichen übereinstimmt .^
markiert den Anfang der Linie,$
ihr EndeAndere Suchmusterbeispiele für egrep :
Ersetzen Sie das
egrep -i -q "^cover\.(jpg|png)$"
Teil durch:egrep -i -q "cover\.(jpg|png)$"
: Auch passtcd_cover.png
,album_cover.JPG
...egrep -q "^cover\.(jpg|png)$"
: Übereinstimmungencover.png
,cover.jpg
aber NICHTCover.jpg
(Groß- / Kleinschreibung ist nicht deaktiviert)egrep -iq "^(cover|front)\.jpg$"
: Passt zBfront.jpg
,Cover.JPG
aber nichtCover.PNG
Weitere Informationen hierzu finden Sie unter Reguläre Ausdrücke .
quelle
test
.-exec bash -c '[[ -n $(find "{}" -iname "cover.*") ]]' \;
aber das ist in Bezug auf die Optimierung ziemlich dreckig. Es funktioniert aber.test
eine-o EXPRESSION
Menge übergeben können ... ztest -e "{}/cover.jpg" -o -e "{}/cover.png"
.$
im Verzeichnisnamen befinden (z. B. Ke $ ha).Einfach, es stellt sich heraus. Im Folgenden wird eine Liste der Verzeichnisse mit dem Cover abgerufen und diese mit einer Liste aller Verzeichnisse der zweiten Ebene verglichen. Zeilen, die in beiden "Dateien" vorkommen, werden unterdrückt und es verbleibt eine Liste der Verzeichnisse, für die Deckblätter erforderlich sind.
Hurra.
Anmerkungen:
comm
Die Argumente von lauten wie folgt:-1
Unterdrückt Zeilen, die nur für file1 gelten-2
Unterdrücke Zeilen, die für file2 eindeutig sind-3
Zeilen unterdrücken, die in beiden Dateien vorkommencomm
Nimmt nur Dateien, daher die verrückte<(...)
Eingabemethode. Dies leitet den Inhalt über eine echte [temporäre] Datei weiter.comm
benötigt sortierte Eingaben oder es funktioniert nicht undfind
garantiert in keinem Fall eine Bestellung. Es muss auch einzigartig sein. Beim erstenfind
Vorgang wurden mehrere Dateien gefunden,cover.*
sodass möglicherweise doppelte Einträge vorhanden sind.sort -u
kräuselt diese schnell auf eins. Der zweite Fund wird immer einzigartig sein.dirname
ist ein praktisches Tool, um das Verzeichnis einer Datei abzurufen, ohne aufsed
(et al.) zurückzugreifen.find
undcomm
beide sind ein bisschen chaotisch mit ihrer Ausgabe. Das Finalesed
ist da, um die Dinge aufzuräumen, damit du übrig bleibstArtist/Album
. Dies kann für Sie wünschenswert oder nicht wünschenswert sein.quelle
find
kann möglicherweise vereinfacht werdenfind ~/Music/ -iname 'cover.*' -printf '%h\n'
, um die Notwendigkeit zu vermeidendirname
. obwohldirname
anderswo praktisch.Dies ist mit Globbing viel besser zu lösen als mit find.
Nehmen wir nun an, Sie haben keine Streudateien in dieser schönen Struktur. Das aktuelle Verzeichnis enthält nur Interpreten-Unterverzeichnisse und diese enthalten nur Album-Unterverzeichnisse. Dann können wir so etwas machen:
Die
<(...)
Syntax lautet Bash-Prozessersetzung: Sie können einen Befehl anstelle eines Dateiarguments verwenden. Sie können die Ausgabe eines Befehls als Datei behandeln. Wir können also zwei Programme ausführen und deren Diff verwenden, ohne ihre Ausgabe in temporären Dateien zu speichern. Dasdiff
Programm glaubt, dass es mit zwei Dateien arbeitet, aber tatsächlich liest es aus zwei Pipes.Der Befehl, der die rechte Hand eingegeben erzeugt
diff
,printf "%s\n" */*
listet nur die Album - Verzeichnisse. Der Befehl für die linke Hand durchläuft die*.cover
Pfade und gibt deren Verzeichnisnamen aus.Testlauf:
Aha, die
a/b
undfoo/bar
Verzeichnisse haben keinecover.jpg
.Es gibt einige Fälle mit unterbrochenen Ecken, die sich standardmäßig
*
zu sich selbst erweitern, wenn sie mit nichts übereinstimmen. Dies kann mit Bash's behoben werdenset -o nullglob
.quelle
comm
sauberer alsdiff
?comm -3 <(printf "%s\n" */*/cover* | sed -r 's/\/[^\/]+$//' | sort -u) <(printf "%s\n" */*)
scheint wie ein vernünftiger Kompromiss ohnediff
Flusen. Es ist jedoch etwas langsamer als mein Doppelfund.Zeigt alle Verzeichnisse an, in denen sich keine txt-Dateien befinden.
quelle