¿Comodines recursivos en GNU?

Resuelto Roger Lipscombe asked hace 14 años • 7 respuestas

Ha pasado un tiempo desde que lo usé make, así que tengan paciencia conmigo...

Tengo un directorio flacque contiene archivos .FLAC. Tengo un directorio correspondiente que mp3contiene 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 flacdirectorio de forma recursiva y crear los subdirectorios correspondientes en el mp3directorio. Los directorios y archivos pueden tener espacios en los nombres y se denominan en UTF-8.

Y quiero usarlo makepara conducir esto.

Roger Lipscombe avatar Mar 20 '10 20:03 Roger Lipscombe
Aceptado

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 makeprincipiantes:

  • El @frente de los comandos impide makeimprimir 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 makeutiliza 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 :-/

ndim avatar Mar 20 '2010 13:03 ndim

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 .cy .hen src:

$(call rwildcard,src,*.c *.h)

Esta función se basa en la implementación de este artículo , con algunas mejoras.

 avatar Aug 15 '2013 17:08

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

kenorb avatar May 10 '2015 18:05 kenorb

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_MANIFESTvariable 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 .

Michael Shebanow avatar Dec 03 '2011 20:12 Michael Shebanow