Cela fait un moment que je n'ai pas utilisé make
, alors supportez-moi ...
J'ai un répertoire flac
, contenant des fichiers .FLAC. J'ai un répertoire correspondant, mp3
contenant des fichiers MP3. Si un fichier FLAC est plus récent que le fichier MP3 correspondant (ou si le fichier MP3 correspondant n'existe pas), je souhaite exécuter un tas de commandes pour convertir le fichier FLAC en fichier MP3 et copier les balises.
Le kicker: je dois rechercher le flac
répertoire de manière récursive et créer les sous-répertoires correspondants dans le mp3
répertoire. Les répertoires et fichiers peuvent avoir des espaces dans les noms et sont nommés en UTF-8.
Et je veux utiliser make
pour conduire cela.
make
sont plus proches de sa mise en œuvre que nuesbash
.sh
script qui parcourt la liste des fichiers flac (find | while read flacname
), crée un àmp3name
partir de là, exécute "mkdir -p" sur ledirname "$mp3name"
, puis seif [ "$flacfile" -nt "$mp3file"]
convertit"$flacname"
en"$mp3name"
n'est pas vraiment magique. La seule fonctionnalité que vous perdez réellement par rapport à unemake
solution basée est la possibilité d'exécuterN
des processus de conversion de fichiers en parallèle avecmake -jN
.make
et la présence d'espaces dans les noms de fichiers sont des exigences contradictoires. Utilisez un outil adapté au domaine du problème.Réponses:
J'essaierais quelque chose de ce genre
Quelques notes rapides pour les
make
débutants:@
devant des commandes empêchemake
d'imprimer la commande avant de l'exécuter.$(@D)
est la partie répertoire du nom du fichier cible ($@
)Même si cela doit gérer tous les caractères UTF-8 et autres choses, il échouera aux espaces dans les noms de fichiers ou de répertoires, car il
make
utilise des espaces pour séparer les éléments dans les fichiers makefiles et je ne suis pas au courant d'un moyen de contourner cela. Donc, cela ne vous laisse qu'un script shell, j'ai peur: - /la source
vpath
. Doit étudier ça un de ces jours.find
pour obtenir les noms de manière récursive ...make -jN
. PourN
utiliser le nombre de conversions quimake
doivent s'exécuter en parallèle. Attention: L'exécutionmake -j
sans anN
lancera tous les processus de conversion en même temps en parallèle, ce qui pourrait être équivalent à une bombe à fourche..PHONY: all
ligne indique à make que la recette de laall
cible doit être exécutée même s'il existe un fichier appeléall
plus récent que tous les$(MP3_FILES)
.Vous pouvez définir votre propre fonction générique récursive comme ceci:
Le premier paramètre (
$1
) est une liste de répertoires, et le second ($2
) est une liste de modèles que vous souhaitez faire correspondre.Exemples:
Pour trouver tous les fichiers C dans le répertoire courant:
Pour trouver tous les fichiers
.c
et.h
danssrc
:Cette fonction est basée sur l'implémentation de cet article , avec quelques améliorations.
la source
make
un goudron de Turing (voir ici: yosefk.com/blog/fun-at-the-turing-tar-pit.html ). Ce n'est même pas si difficile, mais il faut lire ceci: gnu.org/software/make/manual/html_node/Call-Function.html et ensuite "comprendre la récurrence". VOUS deviez écrire ceci de manière récursive, au sens littéral du terme; ce n'est pas la compréhension quotidienne de "inclure automatiquement des éléments des sous-répertoires". C'est la RÉCURRENCE réelle. Mais rappelez-vous - "Pour comprendre la récurrence, vous devez comprendre la récurrence".FWIW, j'ai utilisé quelque chose comme ça dans un Makefile :
L'exemple ci-dessus recherchera dans le répertoire courant ( '.' ) Tous les "fichiers simples" ( '-type f' ) et définira la
RECURSIVE_MANIFEST
variable make sur chaque fichier qu'il trouve. Vous pouvez ensuite utiliser des substitutions de modèles pour réduire cette liste ou, alternativement, fournir plus d'arguments à find pour restreindre ce qu'il renvoie. Consultez la page de manuel pour trouver .la source
Ma solution est basée sur celle ci-dessus, utilise
sed
au lieu depatsubst
pour modifier la sortie defind
ET échapper aux espaces.Passer de flac / à ogg /
Mises en garde:
la source
Voici un script Python que j'ai rapidement piraté ensemble pour résoudre le problème d'origine: conserver une copie compressée d'une bibliothèque musicale. Le script convertira les fichiers .m4a (supposés être ALAC) au format AAC, sauf si le fichier AAC existe déjà et est plus récent que le fichier ALAC. Les fichiers MP3 de la bibliothèque seront liés, car ils sont déjà compressés.
Méfiez-vous simplement que l'annulation du script (ctrl-c ) laissera un fichier à moitié converti.
À l'origine, je voulais aussi écrire un Makefile pour gérer cela, mais comme il ne peut pas gérer les espaces dans les noms de fichiers (voir la réponse acceptée) et parce que l'écriture d'un script bash est garantie de me mettre dans un monde de douleur, c'est Python. C'est assez simple et court, et devrait donc être facile à adapter à vos besoins.
Bien entendu, cela peut être amélioré pour effectuer le codage en parallèle. Cela est laissé comme exercice au lecteur ;-)
la source
Si vous utilisez Bash 4.x, vous pouvez utiliser une nouvelle option de globbing , par exemple:
Ce type de joker récursif peut trouver tous les fichiers qui vous intéressent ( .flac , .mp3 ou autre). O
la source
**
ne fonctionnera pas, car le globbing étendu est une chose bash / zsh.