Es ist schon eine Weile her, seit ich es benutzt habe make
, also nimm es mit ...
Ich habe ein Verzeichnis flac
mit FLAC-Dateien. Ich habe ein entsprechendes Verzeichnis mp3
mit MP3-Dateien. Wenn eine FLAC-Datei neuer als die entsprechende MP3-Datei ist (oder die entsprechende MP3-Datei nicht vorhanden ist), möchte ich eine Reihe von Befehlen ausführen, um die FLAC-Datei in eine MP3-Datei zu konvertieren und die Tags zu kopieren.
Der Kicker: Ich muss das flac
Verzeichnis rekursiv durchsuchen und entsprechende Unterverzeichnisse im mp3
Verzeichnis erstellen . Die Verzeichnisse und Dateien können Leerzeichen in den Namen enthalten und werden in UTF-8 benannt.
Und ich möchte make
damit fahren.
make
näher an der Implementierung als bloßbash
.sh
Skript , das die Liste der FLAC - Dateien geht durch (find | while read flacname
), macht einemp3name
davon läuft „mkdir -p“ auf dasdirname "$mp3name"
, und dannif [ "$flacfile" -nt "$mp3file"]
wandelt"$flacname"
in"$mp3name"
nicht wirklich Magie. Die einzige Funktion, die Sie im Vergleich zu einermake
basierten Lösung tatsächlich verlieren, ist die Möglichkeit,N
Dateikonvertierungsprozesse parallel zu auszuführenmake -jN
.make
und das Vorhandensein von Leerzeichen in Dateinamen sind widersprüchliche Anforderungen. Verwenden Sie ein für die Problemdomäne geeignetes Tool.Antworten:
Ich würde etwas in diese Richtung versuchen
Ein paar kurze Hinweise für
make
Anfänger:@
vor den Befehlen stehendemake
Befehl verhindert, dass der Befehl gedruckt wird, bevor er tatsächlich ausgeführt wird.$(@D)
ist der Verzeichnisteil des Zieldateinamens ($@
)Selbst wenn dies alle UTF-8-Zeichen und -Stücke behandeln sollte, schlägt dies an Stellen in Datei- oder Verzeichnisnamen fehl, da
make
Leerzeichen verwendet werden, um Sachen in den Makefiles zu trennen, und mir ist keine Möglichkeit bekannt, dies zu umgehen . Ich fürchte, Sie haben nur noch ein Shell-Skript: - /quelle
vpath
. Muss das eines Tages studieren.find
, um die Namen rekursiv zu erhalten ...make -jN
. ZurN
Verwendung die Anzahl der Konvertierungen, diemake
parallel ausgeführt werden sollen. Achtung: Wenn Siemake -j
ohneN
laufen, werden alle Konvertierungsvorgänge gleichzeitig parallel gestartet, was möglicherweise einer Gabelbombe entspricht..PHONY: all
Zeile sagt make, dass das Rezept für dasall
Ziel ausgeführt werden soll, auch wenn es eine Datei gibt, dieall
neuer heißt als alle$(MP3_FILES)
.Sie können Ihre eigene rekursive Platzhalterfunktion folgendermaßen definieren:
Der erste Parameter (
$1
) ist eine Liste von Verzeichnissen und der zweite ($2
) ist eine Liste von Mustern, mit denen Sie übereinstimmen möchten.Beispiele:
So finden Sie alle C-Dateien im aktuellen Verzeichnis:
So finden Sie alle
.c
und.h
Dateien insrc
:Diese Funktion basiert auf der Implementierung aus diesem Artikel mit einigen Verbesserungen.
quelle
make
ist eine Turing-Teergrube (siehe hier: yosefk.com/blog/fun-at-the-turing-tar-pit.html ). Es ist nicht einmal so schwer, aber man muss dies lesen: gnu.org/software/make/manual/html_node/Call-Function.html und dann "Wiederholung verstehen". SIE mussten dies rekursiv im wörtlichen Sinne schreiben; Es ist nicht das alltägliche Verständnis von "automatisch Dinge aus Unterverzeichnissen einschließen". Es ist tatsächlich RECURRENCE. Aber denken Sie daran: "Um die Wiederholung zu verstehen, müssen Sie die Wiederholung verstehen."FWIW, ich habe so etwas in einem Makefile verwendet :
Im obigen Beispiel wird aus dem aktuellen Verzeichnis ( '.' ) Nach allen "einfachen Dateien" ( '-type f' ) gesucht und die
RECURSIVE_MANIFEST
Variable make auf jede gefundene Datei gesetzt. Sie können dann Musterersetzungen verwenden, um diese Liste zu verkleinern, oder alternativ mehr Argumente in find angeben, um die Rückgabe einzugrenzen. Weitere Informationen finden Sie in der Manpage .quelle
Meine Lösung basiert auf der obigen, verwendet,
sed
anstattpatsubst
die Ausgabe vonfind
AND zu entstellen, um die Leerzeichen zu verlassen.Von flac / nach ogg /
Vorsichtsmaßnahmen:
quelle
Hier ist ein Python-Skript, das ich schnell zusammen gehackt habe, um das ursprüngliche Problem zu lösen: Behalte eine komprimierte Kopie einer Musikbibliothek. Das Skript konvertiert .m4a-Dateien (vermutlich ALAC) in das AAC-Format, es sei denn, die AAC-Datei ist bereits vorhanden und neuer als die ALAC-Datei. MP3-Dateien in der Bibliothek werden verknüpft, da sie bereits komprimiert sind.
Beachten Sie jedoch, dass beim Abbrechen des Skripts ( ctrl-c) eine halb konvertierte Datei zurückbleibt.
Ich wollte ursprünglich auch ein Makefile schreiben, um dies zu handhaben, aber da es keine Leerzeichen in Dateinamen verarbeiten kann (siehe die akzeptierte Antwort) und weil das Schreiben eines Bash-Skripts mich garantiert in eine Welt voller Schmerzen versetzt, ist es Python. Es ist ziemlich einfach und kurz und sollte daher leicht an Ihre Bedürfnisse anzupassen sein.
Dies kann natürlich verbessert werden, um die Codierung parallel durchzuführen. Das bleibt dem Leser als Übung überlassen ;-)
quelle
Wenn Sie Bash 4.x verwenden, können Sie eine neue Globbing-Option verwenden , zum Beispiel:
Diese Art von rekursivem Platzhalter kann alle Dateien von Interesse finden ( .flac , .mp3 oder was auch immer). Ö
quelle
**
funktioniert es nicht, da das erweiterte Globbing eine Bash / Zsh-Sache ist.