Como altero a extensão de vários arquivos?


168

Gostaria de alterar uma extensão de arquivo de *.txtpara *.text. Tentei usar o basenamecomando, mas estou tendo problemas para alterar mais de um arquivo.

Aqui está o meu código:

files=`ls -1 *.txt`

for x in $files
do
    mv $x "`basename $files .txt`.text"
done

Estou recebendo este erro:

basename: too many arguments Try basename --help' for more information

Respostas:


176

Diretamente da Wiki de Greg :

# Renomeie todos * .txt para * .text
para f em * .txt; Faz
    mv - "$ f" "$ {f% .txt} .text"
feito

Veja também a entrada sobre por que você não deve analisarls .

Edit: se você tiver que usar basenamesua sintaxe seria:

para f em * .txt; Faz
    mv - "$ f" "$ (nome da base -" $ f ".txt) .text"
feito

48
Há alguma sintaxe do Bash um pouco avançada usada aqui sem explicação. Eu tive que procurar muitas coisas no Google para entender isso completamente. Para ajudar outras pessoas na minha posição, aqui estão algumas referências sobre globs (a *.txtsintaxe) , o traço duplo simples-- e o uso do símbolo% na ${}construção . Até agora, eu nunca tinha encontrado os dois últimos e não sabia o que realmente estava acontecendo com o primeiro.
Mark Amery

3
Veja a resposta de Matthias Braun abaixo - muito mais simples, realiza a mesma coisa.
btk

10
Um linerfor f in *.txt; do mv -- "$f" "${f%.txt}.text"; done
Marçal Juan

11
Você está desaparecido; depois do texto ".
Pétur Ingi Egilsson 28/01

2
@ PéturIngiEgilsson na segunda linha? Não, não é necessário.
precisa saber é o seguinte

132

Aqui está como eu mudo todas as extensões de arquivo no diretório atual do Debian.

rename "s/oldExtension/newExtension/" *.txt

(Este é o Perl renamecomando, e não a util-linuxum. Veja Por que é o utilitário de renomeação no Debian / Ubuntu diferente do que em outras distribuições, como o CentOS? )


10
Muito mais simples que a resposta aceita, obrigado!
btk

8
No Mac, eu consegui brew install renamee isso funcionou.
Monkpit

3
com shell peixes que você pode fazer rename "s/oldExtension/newExtension/" **.txtpara mudar o nome all * .txt recursivamente
Palmstrom

3
Isso irá falhar footxt.txt. Em vez disso, use isto: unix.stackexchange.com/questions/19654/…
wisbucky 1/17/17

7
Quando os arquivos não tem qualquer extensão e pretende adicionar um:rename 's/$/.txt/' *
mkataja

35

Um comando simples, o renamefromutil-linux , fará isso por você, substituindo todas as ocorrências de "txt" por "text" em todos os arquivos correspondentes a "* .txt":

rename txt text *.txt

4
renamealtera a primeira ocorrência, é melhor fazer isso rename .txt .text, mas isso nem sempre funciona (por exemplo, renomeia foo.txtx.bar.txtpara foo.textx.bar.txt).
Gilles

12
Note-se que nem todos os sistemas têm a mesma versão de renomeação; no Debian e nos amigos, o renamecomando é realmente perl-renamee usa expressões regulares perl. Para isso, o comando equivalente seria: rename 's/.txt/.text/' *.txt. As pessoas devem verificar o man renamesistema para descobrir qual delas possuem.
evilsoup

@evilsoup Esse é o caso para OSX, thx
Davi Lima

Isso também funciona em Cygwin (Windows)
andy

27
rename "s/oldExtension/newExtension/" *.txt

Acima funciona bem, mas limitado ao diretório atual. Experimente o comando abaixo, que é flexível com subdiretórios. Ele renomeará todos os .txtarquivos na estrutura de diretórios com uma nova extensão.

find . -name "*.txt" -exec rename 's/.txt$/.newext/' {} \;

2
renamepode lidar com vários arquivos como argumento, você pode vastamente acelerar as coisas, usando +, em vez de \;se há muitos desses arquivos
Anthon

Ainda assim, é uma opção útil, pois "* .txt" pode ser aberto em uma grande lista de argumentos não suportada pelo shell.
Roman Shapovalov

11
"falhará em s / oldExtension / newExtension /" footxt.txt. Em vez disso, use isto: unix.stackexchange.com/questions/19654/…
wisbucky 1/17/17


9

As respostas aqui referenciadas s/oldExtension/newExtension/estão erradas. Se você usar s/txt/text/, você converterá footxt.txtpara footext.txt, que não é o que você deseja. Mesmo se você usar s/.txt/.text/, isso seria convertido footxt.txtpara fo.text.txt.

Você precisa usar \.para corresponder ao período ( .corresponderá a qualquer caractere). E o final $para coincidir com o final da linha. Somente isso corresponderá corretamente à extensão.

rename 's/\.txt$/.text/' *.txt

rename 's/\.old$/.new/' *.old

7

Com base na resposta do @Prince John Wesley, aqui está um script simples para alterar todas as extensões de arquivos no diretório atual de ext1para ext2. Também gera nomes dos arquivos que estão sendo renomeados.

#!/bin/bash
for f in *.$1
do
    [ -f "$f" ] && mv -v "$f" "${f%$1}$2"
done

Exemplo de uso (assumindo que o nome do script seja change-ext):

change-ext ext1 ext2

Para alterar as extensões de arquivos nos diretórios recursivamente, substitua a segunda linha ( for...) por duas linhas: shopt -s globstare for f in **/*.$1. Requer Bash 4+.
Dennis Golomazov 02/02/2012

4

Razão # 53 para mudar para zsh:

zmv '(*).txt' '$1.text'


3

digamos que seus arquivos estão espalhados em vários diretórios. Supondo que dirx seja seu diretório pai, isso pode ser feito usando find:

for f in `find /dirx -iname '*.txt' -type f -print`;do  mv "$f" ${f%.txt}.text; done

E sobre tcsh ..
Josef Klimuk

2

Isto é o que funciona para mim:

find . -name '*.txt' -exec rename 's/\.txt$/.text/' \{} \;

11
POR FAVOR, adicione um. antes do "texto"
danielmhanover

2

Quando você

não tem uma extensão para os arquivos de origem

e a extensão de destino é .text, você faria dessa maneira -

for f in *; do mv -- "$f" "${f%.\*}.text"; done

11
Excelente script bash-nativo. funcionou muito bem! for f in *.html; do mv -- "$f" "${f%.\*}.pug"; done
TamusJRoyce 19/07

1

Caso você queira saber o que deu errado na sua versão: Você usou no $fileslugar do $xcomando basename. Portanto, isso deve funcionar (não testado, no entanto):

for x in *.txt
do
  mv "$x" "`basename '$x' .txt`.text"
done
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.