Questão renomear (1) um conjunto de arquivos além do diretório atual


o rename comando no Ubuntu 12.04 (manpage diz que é parte do perl v5.14.2 2012-03-23) funciona bem em um único diretório, mas eu quero usá-lo em subdiretórios também (ou, mais geralmente, em uma lista de arquivos que é o saída de outro comando, via backquotes). Por exemplo, eu esperaria

rename "s/ /-/g"  `find .`

para alterar todos os espaços para traços em todos os nomes de arquivos abaixo do diretório atual. Mas esse comando não faz nada.

(Editar: mudou rename -n para rename. Essa opção é boa para experimentar com segurança, mas apenas uma distração aqui.)

As backquotes não estão em falta, porque a substituição find . com por ex. echo */* trabalho.

Primeiro fazendo find . > fooe, em seguida, substituindo find . com cat foo, faz nada.

Mesmo colapso da lista de arquivos em uma linha, substituindo find . com find . | tr -d '\n', faz nada.

Qual elemento está com defeito?


3


origem




Respostas:


Isso não funcionará:

rename 's/ /-/g'  `find .`

Depois de executar o comando find, o shell faz a divisão de palavras nos resultados. Conseqüentemente, nenhum nome de arquivo com espaços sobrevive ao tato: ele é dividido em partes.

Você pode evitar isso usando:

rename 's/ /-/g'  */*

Nesta forma de comando, o shell não faz a divisão de palavras e o seu rename terá sucesso. Este formulário funciona mesmo para nomes de arquivos com espaços, tabulações ou quaisquer outros caracteres difíceis.

Como alternativa, use find's -exec:

find . -name '* *' -exec rename 's/ /-/g' {} +

Este formulário funcionará com nomes de arquivos com espaços, tabulações ou quaisquer outros caracteres difíceis.

Demonstração

Para ver o que está errado, vamos criar um arquivo com espaços

$ touch "a b c"
$ find .
.
./a b c

Para esclarecer o que acontece, vamos criar uma função para colocar cada argumento que ele vê dentro de aspas duplas e exibi-lo:

$ display() { printf '"%s"\n' "$@"; }

Agora podemos usar display para ver o que acontece quando corremos find .:

$ display `find .`
"."
"./a"
"b"
"c"

Isso mostra a divisão de palavras em ação. O nome do arquivo a b c foi dividido em três palavras separadas.


2



"in tact": vejo o que você fez lá :-) - Camille Goudeseune
Espaços em branco em nomes de arquivos é apenas um exemplo: um melhor pode ser s/png/jpg/. Então, é isso geral resposta reduz a solução para a substituição de backquotes com find ... -exec rename ...ou find ... | xargs rename .... Então eu ainda me pergunto por que os backquotes falham. - Camille Goudeseune
@CamilleGoudeseune "Então eu ainda me pergunto por que os backquotes falham." Não tem nada a ver com qual comando substituto é usado. É porque os nomes de arquivos com espaço em branco na linha de comando estão sujeitos à divisão de palavras. Caso contrário, funciona. - John1024
Corrigir. O espaço em branco em nomes de arquivos é o só problema, afinal. Fiz um teste melhor do zero e, sim, backquotes funcionam. Desculpe por desperdiçar seu tempo. - Camille Goudeseune