Respostas:
Para uma solução melhor (apenas com funcionalidade bash, em oposição a chamadas externas), consulte uma das outras respostas .
O seguinte requer e não exige que o sistema possua o rename
programa (embora você o possua com mais freqüência em um sistema):
for file in *.html; do
mv "$file" "$(basename "$file" .html).txt"
done
EDIT: Como apontado nos comentários, isso não funciona para nomes de arquivos com espaços neles sem uma citação adequada (agora adicionada acima). Ao trabalhar exclusivamente em seus próprios arquivos que você sabe que não têm espaços nos nomes dos arquivos, isso funcionará, mas sempre que você escrever algo que possa ser reutilizado posteriormente, não pule a citação adequada.
ren *.a *.b
$()
sintaxe especificada pelo POSIX em vez da sintaxe do backtick herdado. Melhora a legibilidade e torna a sintaxe muito menos ambígua quando você tem caracteres que precisariam ser escapados por barra invertida para serem literais dentro da substituição de comando pelo último.
Se estiver usando o bash, não há necessidade de comandos externos, como sed, basename, rename, expr, etc.
for file in *.html
do
mv "$file" "${file%.html}.txt"
done
"${file%.*}.txt"
, mas isso pode ser perigoso para arquivos sem uma extensão.
$
dentro do aparelho!
--
"operator": mv - "$ file" "$ {file% .html} .txt" Esse operador evita nomes de arquivos que começam com um '-' de ser analisado por mv como argumentos.
rename 's/\.html$/\.txt/' *.html
faz exatamente o que você quer.
Isso funcionou para mim no OSX de .txt a .txt_bak
find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;
.txt
que .txt_bak
você só tem que concatenar _bak
;)
.scss
para .sass
(após a conversão no local…):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Você quer usar rename
:
rename -S .html .txt *.html
Isso faz exatamente o que você deseja - alterará a extensão de .html
para .txt
para todos os arquivos correspondentes *.html
.
Nota: Greg Hewgill indica corretamente que este não é um bash embutido; e é um comando Linux separado. Se você só precisa de algo no Linux, isso deve funcionar bem; se você precisar de algo mais entre plataformas, dê uma olhada em uma das outras respostas.
rename
programa não está relacionado bash
e também não está disponível em todas as plataformas. Eu só vi isso no Linux.
rename -S .html .text *.html
onde -S
significa--subst-all
Para usuários do Ubuntu:
rename 's/\.html$/\.txt/' *.html
Aqui está um exemplo do comando renomear:
rename -n ’s/\.htm$/\.html/’ *.htm
O -n significa que é uma execução de teste e, na verdade, não altera nenhum arquivo. Ele mostrará uma lista de arquivos que seriam renomeados se você removesse o -n. No caso acima, ele converterá todos os arquivos no diretório atual de uma extensão de arquivo .htm para .html.
Se a saída da execução de teste acima parecer boa, você poderá executar a versão final:
rename -v ’s/\.htm$/\.html/’ *.htm
O -v é opcional, mas é uma boa idéia incluí-lo, pois é o único registro que você terá das alterações que foram feitas pelo comando rename, conforme mostrado na amostra de saída abaixo:
$ rename -v 's/\.htm$/\.html/' *.htm
3.htm renamed as 3.html
4.htm renamed as 4.html
5.htm renamed as 5.html
A parte complicada do meio é uma substituição de Perl com expressões regulares, destacada abaixo:
rename -v ’s/\.htm$/\.html/’ *.htm
Esta pergunta menciona explicitamente o Bash, mas se você tiver o ZSH disponível, é bastante simples:
zmv '(*).*' '$1.txt'
Se você conseguir zsh: command not found: zmv
, basta executar:
autoload -U zmv
E então tente novamente.
Obrigado a este artigo original pela dica sobre o zmv.
Após o rastreamento do site de outra pessoa, acabei com milhares de arquivos ausentes na extensão .html, em uma grande árvore de subdiretórios.
Para renomear todos eles de uma só vez, exceto os arquivos que já possuem uma extensão .html (a maioria deles não tinha nenhuma), isso funcionou para mim:
cd wwwroot
find . -xtype f \! -iname *.html -exec mv -iv "{}" "{}.html" \; # batch rename files to append .html suffix IF MISSING
No caso do OP, eu posso modificar isso um pouco, para renomear apenas arquivos * .txt, da seguinte maneira:
find . -xtype f -iname *.txt -exec filename="{}" mv -iv ${filename%.*}.{txt,html} \;
Quebrado (hora do martelo!):
-iname * .txt
- significa considerar SOMENTE arquivos que já terminam em .txt
mv -iv "{}. {txt, html}" - Quando find passa a {} como o nome do arquivo, $ {filename%. *} extrai seu nome de base sem nenhuma extensão para formar os parâmetros para mv . o bash usa o {txt, html} para reescrevê-lo como dois parâmetros, para que o comando final seja executado como:mv -iv "filename.txt" "filename.html"
Correção necessária: lidar com espaços nos nomes de arquivos
O comandommv
parece executar essa tarefa com muita eficiência em um grande número de arquivos (dezenas de milhares em um segundo). Por exemplo, para renomear todos os .xml
arquivos para .html
arquivos, use este:
mmv ";*.xml" "#1#2.html"
o ;
corresponderá ao caminho, *
corresponderá ao nome do arquivo e estes serão referidos como #1
e #2
no nome de substituição.
As respostas baseadas em exec
ou pipes foram muito lentas ou com falha em um número muito grande de arquivos.
Tente isto
rename .html .txt *.html
uso:
rename [find] [replace_with] [criteria]
Um pouco atrasado para a festa. Você poderia fazer isso com xargs:
ls *.html | xargs -I {} sh -c 'mv $1 `basename $1 .html`.txt' - {}
Ou se todos os seus arquivos estiverem em alguma pasta
ls folder/*.html | xargs -I {} sh -c 'mv $1 folder/`basename $1 .html`.txt' - {}
ls
. Não analise . Esse comando é ridículo: ele usa um glob inutilmente ls
, em vez de usar diretamente o glob. Isso quebrará os nomes de arquivos que contêm espaços, aspas e (devido à falta de aspas) caracteres glob.
Esta é uma boa maneira de modificar várias extensões ao mesmo tempo:
for fname in *.{mp4,avi}
do
mv -v "$fname" "${fname%.???}.mkv"
done
Nota: tenha cuidado com o tamanho da extensão para ser o mesmo (o ???)
Se você preferir PERL, existe um pequeno script PERL (originalmente escrito por Larry Wall, o criador do PERL) que fará exatamente o que você deseja aqui: tips.webdesign10.com/files/rename.pl.txt .
Para o seu exemplo, o seguinte deve fazer o truque:
rename.pl 's/html/txt/' *.html
Similar ao que foi sugerido antes, foi assim que eu fiz:
find . -name '*OldText*' -exec sh -c 'mv "$0" "${0/OldText/NewText}"' {} \;
Eu primeiro validei com
find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;
Uma linha, sem loops:
ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
Exemplo:
$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.json ac8453e2-0d82-4d43-b80e-205edb754700.json
$ ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.txt ac8453e2-0d82-4d43-b80e-205edb754700.txt
Infelizmente, não é trivial fazer portably. Você provavelmente precisa de um pouco de magia expr.
for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done
Remova o eco quando estiver feliz, pois ele faz o que deseja.
Edit: basename
provavelmente é um pouco mais legível para este caso em particular, embora expr
seja mais flexível em geral.
Aqui está o que eu costumava renomear .edge
arquivos para.blade.php
for file in *.edge; do mv "$file" "$(basename "$file" .edge).blade.php"; done
Funciona como charme.
Você também pode criar uma função no Bash, adicioná-la .bashrc
ou algo assim e usá-la onde quiser.
change-ext() {
for file in *.$1; do mv "$file" "$(basename "$file" .$1).$2"; done
}
Uso:
change-ext css scss
Origem do código na função: https://stackoverflow.com/a/1224786/6732111
Renomeie as extensões de arquivo para todos os arquivos no diretório e subdiretórios atuais sem outros pacotes (use apenas o shell script):
Crie um script de shell rename.sh
no diretório atual com o seguinte código:
#!/bin/bash
for file in $(find . -name "*$1"); do
mv "$file" "${file%$1}$2"
done
Corra ./rename.sh .old .new
.
Por exemplo. ./rename.sh .html .txt