Já faz um tempo desde que eu uso make
, então tenha paciência comigo ...
Eu tenho um diretório flac
,, contendo arquivos .FLAC. Eu tenho um diretório correspondente, mp3
contendo arquivos MP3. Se um arquivo FLAC for mais recente que o arquivo MP3 correspondente (ou o arquivo MP3 correspondente não existir), quero executar vários comandos para converter o arquivo FLAC em MP3 e copiar as tags.
O kicker: eu preciso pesquisar o flac
diretório recursivamente e criar subdiretórios correspondentes no mp3
diretório. Os diretórios e arquivos podem ter espaços nos nomes e são nomeados em UTF-8.
E eu quero usar make
para dirigir isso.
make
está mais perto de implementá-la do que simplesbash
.sh
script que percorre a lista de arquivos flac (find | while read flacname
), faz um amp3name
partir disso, executa "mkdir -p" nodirname "$mp3name"
e entãoif [ "$flacfile" -nt "$mp3file"]
converte"$flacname"
em"$mp3name"
não é realmente mágico. O único recurso que você está realmente perdendo em comparação com umamake
solução baseada é a possibilidade de executarN
processos de conversão de arquivos em paralelo commake -jN
.make
e ter espaços nos nomes dos arquivos são requisitos contraditórios. Use uma ferramenta apropriada para o domínio do problema.Respostas:
Eu tentaria algo nesse sentido
Algumas notas rápidas para
make
iniciantes:@
na frente dos comandos impede amake
impressão do comando antes de realmente executá-lo.$(@D)
é a parte do diretório do nome do arquivo de destino ($@
)Mesmo que isso deva lidar com todos os caracteres UTF-8 e outras coisas, ele falhará em espaços nos nomes de arquivo ou diretório, pois
make
usa espaços para separar coisas nos makefiles e não estou ciente de uma maneira de contornar isso. Então isso deixa você com apenas um script de shell, infelizmente: - /fonte
vpath
. Devo estudar isso um dia desses.find
para obter os nomes recursivamente ...make -jN
. ParaN
usar o número de conversões quemake
devem ser executadas em paralelo. Cuidado: Executarmake -j
sem umN
iniciará todos os processos de conversão de uma vez em paralelo, o que pode ser equivalente a uma bomba fork..PHONY: all
linha diz ao make que a receita para oall
alvo deve ser executada mesmo se houver um arquivo chamadoall
mais recente que todos os$(MP3_FILES)
.Você pode definir sua própria função curinga recursiva assim:
O primeiro parâmetro (
$1
) é uma lista de diretórios e o segundo ($2
) é uma lista de padrões que você deseja corresponder.Exemplos:
Para encontrar todos os arquivos C no diretório atual:
Para encontrar todas as
.c
e.h
arquivos emsrc
:Esta função é baseada na implementação deste artigo , com algumas melhorias.
fonte
make
é um Turing Tar Pit (veja aqui: yosefk.com/blog/fun-at-the-turing-tar-pit.html ). Não é nem tão difícil, mas é preciso ler isso: gnu.org/software/make/manual/html_node/Call-Function.html e então "entender a recorrência". VOCÊ teve que escrever isso recursivamente, no sentido literal; não é o entendimento diário de "incluir automaticamente coisas de subdiretórios". É RECORRÊNCIA real. Mas lembre-se - "Para entender a recorrência, você tem que entender a recorrência".FWIW, usei algo assim em um Makefile :
O exemplo acima irá pesquisar no diretório atual ( '.' ) Por todos os "arquivos simples" ( '-tipo f' ) e definir a
RECURSIVE_MANIFEST
variável make para cada arquivo que encontrar. Você pode então usar substituições de padrão para reduzir essa lista ou, alternativamente, fornecer mais argumentos em find para restringir o que ela retorna. Veja a página do manual para encontrar .fonte
Minha solução é baseada na acima, usa ao
sed
invés depatsubst
mangle a saída defind
AND escapar dos espaços.Indo de flac / para ogg /
Ressalvas:
fonte
Aqui está um script Python que eu criei rapidamente para resolver o problema original: mantenha uma cópia compactada de uma biblioteca de música. O script converterá os arquivos .m4a (supostamente do ALAC) para o formato AAC, a menos que o arquivo AAC já exista e seja mais recente que o arquivo ALAC. Os arquivos MP3 na biblioteca serão vinculados, uma vez que já estão compactados.
Apenas tome cuidado, pois abortar o script ( ctrl-c) deixará um arquivo convertido pela metade.
Originalmente, eu também queria escrever um Makefile para lidar com isso, mas como ele não pode lidar com espaços em nomes de arquivos (veja a resposta aceita) e porque escrever um script bash certamente me colocará em um mundo de dor, Python é. É bastante simples e curto e, portanto, deve ser fácil de ajustar às suas necessidades.
Claro, isso pode ser aprimorado para realizar a codificação em paralelo. Isso é deixado como um exercício para o leitor ;-)
fonte
Se você estiver usando o Bash 4.x, poderá usar uma nova opção de globbing , por exemplo:
Este tipo de curinga recursivo pode localizar todos os arquivos de seu interesse ( .flac , .mp3 ou qualquer outro). O
fonte
**
não funcionará, porque o globbing estendido é uma coisa bash / zsh.