Crie um script bash para rastrear subdiretórios e executar um comando com ffmpeg

3

atualmente, eu corro este comando ...

# Script designed to convert webm files to m4a for easy listening

for i in *.m4a ; do
    echo ffmpeg -i "\""$PWD/$i"\"" -c:a copy "\""$PWD/${i%.m4a}.mkv"\"" >> ~/bulk.command.txt
done

para criar um arquivo de script que posteriormente possa ser executado para fazer o reempacotamento em lote de arquivos de mídia. Infelizmente este processo requer que eu entre em cada diretório que precisa ser reempacotado e me digita o nome do script.

Às vezes, esses projetos têm vários diretórios e subdiretórios. Além disso, esses projetos, quando ficam grandes, exigem que eu realmente tenha cuidado com o tamanho do diretório raiz do projeto.

Eu ainda estou aprendendo como codificar no bash, e este script simples levou algum tempo para ser aperfeiçoado, para garantir que quase todos os nomes de arquivos possíveis sejam contabilizados.

O que eu gostaria de fazer a seguir é modificá-lo da maneira que eu puder simplesmente ir para a minha pasta de pastas de música, executar este comando uma única vez E também salvar o layout do diretório, mas também colocar os arquivos ffmpeg cria em um diretório diferente. Algum feiticeiro tem alguns exemplos de código, ou termos, ou ideias de como eu posso realizar essa tarefa?

    
por Monery 05.04.2017 / 08:09

1 resposta

3

Habilite a globalização recursiva para recorrer aos subdiretórios:

shopt -s globstar

Então você poderia fazer:

for f in **/*.m4a
do
    printf 'ffmpeg -i %q -c:a copy %q\n' "$PWD/$f" "$PWD/${f%.m4a}.mkv"
done > bulk.command.txt

printf ' %q cita cadeias de caracteres para que possam ser usadas com segurança como entrada de shell, para que você não precise mexer nas cotações:

  %q    quote the argument in a way that can be reused as shell input

Se você criar um script, poderá usar argumentos para decidir se deve usar um diretório diferente para os arquivos de saída:

#! /bin/bash
shopt -s globstar

for f in **/*.m4a
do
    printf 'ffmpeg -i %q -c:a copy %q\n' "$PWD/$f" "${1:-$PWD}/${f%.m4a}.mkv"
done > bulk.command.txt

${foo:-bar} usa o valor da variável foo , se não estiver vazio, ou bar caso contrário, então, neste caso, ele usa o primeiro argumento se não estiver vazio e $PWD caso contrário.

Você precisará recriar a estrutura de diretórios nesse caso, o que pode ser feito com mkdir -p :

#! /bin/bash
shopt -s globstar

for f in **/*.m4a
do
    printf 'mkdir -p %q\n' "${1:-$PWD}/${f%/*}"
    printf 'ffmpeg -i %q -c:a copy %q\n' "$PWD/$f" "${1:-$PWD}/${f%.m4a}.mkv"
done > bulk.command.txt

Isso se você realmente precisar criar um script para uso posterior. Pessoalmente, eu não vejo o ponto - você pode apenas executar o loop diretamente quando você realmente precisa executá-lo:

#! /bin/bash
shopt -s globstar

for f in **/*.m4a
do
    mkdir -p "${1:-$PWD}/${f%/*}"
    ffmpeg -i "$PWD/$f" -c:a copy "${1:-$PWD}/${f%.m4a}.mkv"
done > bulk.command.txt
    
por muru 05.04.2017 / 08:46