Como remover o (1) dos nomes dos arquivos usando o comando find

13

Recentemente, convertei todos os meus arquivos FLAC para uma taxa de amostragem mais baixa de 44,1 kHz e 24 bits de bits (porque o iPhone / iPod não suporta nada acima disso) usando o XLD no Mac OS 10.7 (Lion). / p>

Embora eu tenha dito ao XLD para sobrescrever todos os arquivos anteriores, o XLD anexou um (1) no final de um arquivo como

some_song.m4a

para

some_song(1).m4a

Agora, quero remover esse (1) de todos os arquivos FLAC que converti.

Eu sei que provavelmente poderia ter usado algum programa ou mesmo um AppleScript para renomear os arquivos, mas eu queria aprender usando o modo old school de linha de comando.

Eu sei que find . -name *\(1\).m4a irá pegar todo o arquivo FLAC convertido.

Em seguida, sei que preciso fazer algo com -exec e mv para renomear todos os arquivos encontrados. Mas o que não consigo descobrir é como manter o nome do arquivo original e remover apenas o (1) .

Talvez eu precise fazer captura de regex em grupo para armazenar a parte do nome do arquivo que não quero modificar? Ou talvez não seja possível fazer tudo em uma linha e eu deveria criar um script de shell (que eu não estou tão confortável fazendo, mas estou disposto a tentar).

Todas as dicas ou sugestões são bem-vindas! Obrigado!

    
por hobbes3 11.05.2012 / 20:44

5 respostas

13

Não tente analisar find da saída, exceto como último recurso. É importante perceber que nos sistemas de arquivos Unix, os nomes de arquivos não são sequências (um equívoco comum), mas sim blobs binários que podem conter qualquer caractere, exceto / e o caractere nulo. Analisar nomes de arquivos com segurança e corretamente é o suficiente para uma dor que 99% do tempo você só vai querer evitar fazê-lo completamente (apenas veja como a expressão sed em% a @yarek é e mesmo isso não cobre todos os casos). Felizmente, neste caso, há uma abordagem muito mais simples:

find . -name '*(1).m4a' -execdir sh -c \
'for arg; do mv "$arg" "${arg%(1).m4a}".m4a; done' _ {} \+
    
por 11.05.2012 / 23:05
6

No Debian e no Ubuntu, eu posso usar rename 's/\(1\)//' *.m4a para resolver o seu problema.

    
por 11.05.2012 / 20:54
4

No zsh, usando zmv :

autoload zmv      # you can put this line in your .zshrc
zmv '(*)\(1\)(*)' '$1$2'

No segundo argumento (o novo nome), $1 e $2 referem-se aos grupos de parênteses (PATTERN) no padrão de origem. Outra maneira de escrever esta renomeação é

zmv '(*)' '${1/\(1\)/}'
    
por 12.05.2012 / 04:55
3

A seguinte abordagem lhe dá a capacidade de visualizar / podar os comandos gerados antes executá-los, e é muito portátil: ele deve funcionar não apenas em um mac, não apenas com bash, e não apenas com o GNU sed; mesmo em sistemas sem o comando find (1), é possível substituí-lo por du (1) sem problemas.

find . -name '*(1).m4a' |
sed 's/\(.*\)(1).m4a$/mv & .m4a/' 

Se estiver satisfeito com os comandos impressos, execute novamente com | sh -x anexado.

Se estiver preocupado com espaços em nomes de arquivos, adicione outro s para escapar de todos os espaços:

find . -name '*(1).m4a' |
sed -e 's/ /\ /g' -e 's/\(.*\)(1).m4a$/mv & .m4a/'

Se outros caracteres especiais são esperados, fica um pouco mais complicado:

find . -name '*(1).m4a' |
sed -e "s/'/'\\''/g" -e 's/\(.*\)(1).m4a$/mv '\''&'\'' '\''.m4a'\'/

A primeira função converte todos os ' em uma forma tal que estes são considerados literalmente quando no meio da string '...' -escaped. Segunda função gera comandos mv cujos argumentos estão entre '...' .

    
por 11.05.2012 / 20:54
1

Aqui está um pequeno script que faz isso:

for var in 'find . -type f -name "*(1).m4a"'; do
    new='echo $var | cut -d'(' -f1';
    mv $var $new.m4a;
done
    
por 12.05.2012 / 17:32