adicionar extensão de arquivo recursivamente a todos os arquivos

106

Tenho alguns diretórios e subdiretórios contendo arquivos sem extensão de arquivo. Quero adicionar .jpga todos os arquivos contidos nesses diretórios. Já vi scripts bash para alterar a extensão do arquivo, mas não apenas para adicionar um. Também precisa ser recursivo, alguém pode ajudar por favor?

Robjmills
fonte

Respostas:

228

Comando alternativo sem um loop explícito ( man find):

find . -type f -exec mv '{}' '{}'.jpg \;

Explicação: isto localiza recursivamente todos os arquivos ( -type f) começando do diretório atual ( .) e aplica o comando mover ( mv) a cada um deles. Observe também as aspas ao redor {}, de modo que nomes de arquivos com espaços (e até mesmo novas linhas ...) sejam tratados adequadamente.

Stephan202
fonte
7
Em particular, este funciona melhor se houver um grande número de arquivos na estrutura de diretório (fazendo com que o bash fique chateado com o tamanho da lista de arquivos a serem iterados).
DrAl de
@Al, se você se referir a um forbash perturbador de loop para iterar sobre uma lista de arquivos, isso não está correto. O forloop bash emite iterativamente cada mvcomando.
nik
Pergunta: findPrimeiro configura uma lista de arquivos antes de executar a -execinstrução? Acho que sim, mas quero deixar este ponto claro antes de codificar loops infinitos.
Boldewyn
2
este comando também encontrará arquivos com extensão. É isso que OP quer?
ghostdog74
1
@ ghostdog74: Como ele aceitou essa resposta, o que foi dito acima aparentemente funcionou. Caso contrário, como você mencionou abaixo, adicionar -not -name "*.*"fará o truque.
Stephan202
62

isso encontrará arquivos sem extensão e adicionará seu .jpg

find /path -type f -not -name "*.*" -exec mv "{}" "{}".jpg \;
ghostdog74
fonte
Isso certamente fornecerá o resultado desejado 99% das vezes. +1
les
9

É um pouco tarde, mas pensei em acrescentar que uma solução melhor (embora talvez menos legível) do que as até agora poderia ser:

find /path -type f -not -name "*.*" -print0 | xargs -0 rename 's/(.)$/$1.jpg/'

Usar o find | xargspadrão geralmente resulta em uma execução mais eficiente, pois você não precisa bifurcar um novo processo para cada arquivo.

Observe que isso requer a versão de renomear encontrada em distros com o sabor do Debian (também conhecida como prename), ao invés da renomeação tradicional. É apenas um pequeno script perl, portanto, seria fácil o suficiente para usar o comando acima em qualquer sistema.

Chad Huneycutt
fonte
4

como isso,

for f in $(find . -type f); do mv $f ${f}.jpg; done

Não estou esperando que você tenha nomes de arquivos separados por espaço,
Se os tiver, os nomes precisarão ser processados ​​um pouco.

Se você deseja executar o comando de algum outro diretório,
pode substituir o find .por find /target/directory.

nik
fonte
1
Falta um 'do' e se houver espaços no nome do arquivo, é melhor citar o nome do arquivo: for f em $ (find. -Type f); faça mv "$ f" "$ {f} .jpg"; feito
DrAl de
e presumivelmente eu executaria isso de dentro do diretório de nível superior.
robjmills
@seengee: sim. Observe que este comando também perde o traço -type.
Stephan202
Eu tive que ir a algum lugar e digitei muito rápido ... consertando agora.
nik
1

Para renomear todos os arquivos sem extensão no Windows Basic, você pode fazer uma ren * *.jpg vez que o arquivo não tem extensão, basta usar o *, ou se você quiser mudar o png para jpg useren *.png *.jpg

Nuno
fonte
0

rename

não tenho certeza de que pode renomear arquivos sem extensões (estou no Windows 7 agora)

dfa
fonte
1
pode, mas também renomeará diretórios, e não há como dizer para funcionar recursivamente em subdiretórios (pelo menos com a versão que tenho no Ubuntu).
mirod
Eu conheço pelo menos dois comandos diferentes chamados rename, um programa C incluído no util-linux-ng e um programa Perl (pelo próprio Wall) nas máquinas Debian de nossa universidade. Na verdade, nenhum dos dois faz recursão.
Boldewyn de