Come posso modificare l'estensione di più file?


168

Vorrei cambiare un'estensione di file da *.txta *.text. Ho provato a usare il basenamecomando, ma ho problemi a cambiare più di un file.

Ecco il mio codice:

files=`ls -1 *.txt`

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

Ricevo questo errore:

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

Risposte:


176

Direttamente dal Wiki di Greg :

# Rinomina tutto * .txt in * .text
per f in * .txt; fare
    mv - "$ f" "$ {f% .txt} .text"
fatto

Vedi anche la voce sul perché non dovresti analizzarels .

Modifica: se devi usare basenamela sintassi sarebbe:

per f in * .txt; fare
    mv - "$ f" "$ (basename -" $ f ".txt) .text"
fatto

48
C'è qualche sintassi Bash leggermente avanzata usata qui senza spiegazioni. Ho dovuto a Google molte cose per capirlo appieno. Per aiutare gli altri nella mia posizione, ecco alcuni riferimenti sui globs (la *.txtsintassi) , il doppio trattino nudo-- e l'uso del simbolo% all'interno del ${}costrutto . Fino ad ora non avevo mai incontrato gli ultimi due e non avevo saputo cosa stesse realmente accadendo con il primo.
Mark Amery,

3
Guarda la risposta di Matthias Braun qui sotto: molto più semplice, realizza la stessa cosa.
BTK

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

1
Hai perso; dopo il testo ".
Pétur Ingi Egilsson,

2
@ PéturIngiEgilsson sulla seconda riga? No, non è richiesto.
Jasonwryan,

132

Ecco come cambio tutte le estensioni dei file nella directory corrente su Debian.

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

(Questo è il renamecomando Perl , non util-linuxquello. Vedi Perché l'utilità di rinomina su Debian / Ubuntu è diversa da quella su altre distribuzioni, come CentOS? )


10
Molto più semplice della risposta accettata, grazie!
BTK

8
Su Mac sono stato in grado di brew install renamefarlo funzionare.
Monkpit,

3
con guscio di pesce puoi fare rename "s/oldExtension/newExtension/" **.txtper rinominare tutto * .txt in modo ricorsivo
Palmstrom,

3
Questo fallirà per footxt.txt. Usa questo invece: unix.stackexchange.com/questions/19654/…
wisbucky

7
Quando i tuoi file non hanno alcuna estensione e vuoi aggiungerne uno:rename 's/$/.txt/' *
mkataja

35

Un semplice comando, il renamedautil-linux , lo farà per te, sostituendo tutte le occorrenze di "txt" a "testo" in tutti i file corrispondenti "* .txt":

rename txt text *.txt

4
renamecambia la prima occorrenza, quindi meglio farlo rename .txt .text, ma questo non funzionerà sempre (ad esempio rinominato foo.txtx.bar.txtin foo.textx.bar.txt).
Gilles,

12
Va notato che non tutti i sistemi hanno la stessa versione di rinomina; su Debian e gli amici, il renamecomando è in realtà perl-renamee usa regex perl. Per questo, il comando equivalente sarebbe: rename 's/.txt/.text/' *.txt. Le persone dovrebbero controllare man renamesul proprio sistema per scoprire quale hanno.
evilsoup,

@evilsoup È il caso di OSX, grazie
Davi Lima,

Questo funziona anche su Cygwin (Windows)
andy

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

Sopra funziona bene ma si limita alla directory corrente. Prova il comando seguente, che è flessibile con le sottodirectory. Rinominerà tutti i .txtfile nella struttura di directory con una nuova estensione.

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

2
renamepuò gestire più file come argomento, puoi velocizzare notevolmente le cose usando +invece che \;se ci sono molti di questi file
Anthon,

Tuttavia, è un'opzione utile poiché "* .txt" può essere srotolato in un grande elenco di argomenti non supportato dalla shell.
Roman Shapovalov,

1
"s / oldExtension / newExtension /" non funzionerà per footxt.txt. Usa questo invece: unix.stackexchange.com/questions/19654/…
wisbucky


9

Le risposte qui riferite s/oldExtension/newExtension/sono sbagliate. Se lo usi s/txt/text/, verrai convertito footxt.txtin footext.txt, che non è quello che desideri. Anche se lo usi s/.txt/.text/, si convertirà footxt.txtin fo.text.txt.

Devi usare \.per abbinare il periodo ( .corrisponderà a qualsiasi personaggio). E il finale $per abbinare la fine della linea. Solo questo corrisponderà correttamente all'estensione.

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

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

7

Sulla base della risposta @Prince John Wesley, ecco un semplice script bash per cambiare tutte le estensioni di file nella directory corrente ext1a ext2. Emette anche i nomi dei file che vengono rinominati.

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

Esempio di utilizzo (supponendo che il nome dello script sia change-ext):

change-ext ext1 ext2

Per modificare ricorsivamente le estensioni dei file nelle directory, sostituire la seconda riga ( for...) con due righe: shopt -s globstare for f in **/*.$1. Richiede Bash 4+.
Dennis Golomazov,

4

Motivo # 53 per passare a zsh:

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


3

diciamo che i tuoi file sono sparsi in varie directory, supponendo che dirx sia la tua directory principale, questo può fare il lavoro usando find:

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

Che dire di tcsh ..
Josef Klimuk,

2

Questo è ciò che funziona per me:

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

1
PER FAVORE aggiungi a. prima del "testo"
danielmhanover,

2

Quando tu

non ha un'estensione per i file di origine

e l'estensione di destinazione è .text , lo faresti in questo modo -

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

1
Eccellente script bash nativo. ha funzionato alla grande! for f in *.html; do mv -- "$f" "${f%.\*}.pug"; done
TamusJRoyce,

1

Se vuoi sapere cosa è andato storto nella tua versione: hai usato $filesinvece che $xnel comando basename. Quindi dovrebbe funzionare (non testato):

for x in *.txt
do
  mv "$x" "`basename '$x' .txt`.text"
done
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.