¿Comodines recursivos en GNU?
Ha pasado un tiempo desde que lo usé make
, así que tengan paciencia conmigo...
Tengo un directorio flac
que contiene archivos .FLAC. Tengo un directorio correspondiente que mp3
contiene archivos MP3. Si un archivo FLAC es más nuevo que el archivo MP3 correspondiente (o el archivo MP3 correspondiente no existe), entonces quiero ejecutar una serie de comandos para convertir el archivo FLAC en un archivo MP3 y copiar las etiquetas.
El truco: necesito buscar el flac
directorio de forma recursiva y crear los subdirectorios correspondientes en el mp3
directorio. Los directorios y archivos pueden tener espacios en los nombres y se denominan en UTF-8.
Y quiero usarlo make
para conducir esto.
Probaría algo parecido a esto
FLAC_FILES = $(shell find flac/ -type f -name '*.flac')
MP3_FILES = $(patsubst flac/%.flac, mp3/%.mp3, $(FLAC_FILES))
.PHONY: all
all: $(MP3_FILES)
mp3/%.mp3: flac/%.flac
@mkdir -p "$(@D)"
@echo convert "$<" to "$@"
Un par de notas rápidas para make
principiantes:
- El
@
frente de los comandos impidemake
imprimir el comando antes de ejecutarlo. $(@D)
es la parte del directorio del nombre del archivo de destino ($@
)- Asegúrese de que las líneas con comandos de shell comiencen con una tabulación, no con espacios.
Incluso si esto debería manejar todos los caracteres UTF-8 y demás, fallará en los espacios en los nombres de archivos o directorios, ya que make
utiliza espacios para separar elementos en los archivos MAKE y no conozco una forma de solucionarlo. Entonces eso te deja solo con un script de shell, me temo :-/
Puede definir su propia función comodín recursiva de esta manera:
rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))
El primer parámetro ( $1
) es una lista de directorios y el segundo ( $2
) es una lista de patrones que desea hacer coincidir.
Ejemplos:
Para encontrar todos los archivos C en el directorio actual:
$(call rwildcard,.,*.c)
Para encontrar todos los archivos .c
y .h
en src
:
$(call rwildcard,src,*.c *.h)
Esta función se basa en la implementación de este artículo , con algunas mejoras.
Si estás usando Bash 4.x, puedes usar una nueva opción global , por ejemplo:
SHELL:=/bin/bash -O globstar
list:
@echo Flac: $(shell ls flac/**/*.flac)
@echo MP3: $(shell ls mp3/**/*.mp3)
Este tipo de comodín recursivo puede encontrar todos los archivos de su interés ( .flac , .mp3 o lo que sea). oh
FWIW, he usado algo como esto en un Makefile :
RECURSIVE_MANIFEST = `find . -type f -print`
El ejemplo anterior buscará desde el directorio actual ( '.' ) todos los "archivos simples" ( '-type f' ) y establecerá la RECURSIVE_MANIFEST
variable make para cada archivo que encuentre. Luego puede usar sustituciones de patrones para reducir esta lista o, alternativamente, proporcionar más argumentos a find para limitar lo que devuelve. Consulte la página de manual para buscar .