Come rinominare l'estensione per un mucchio di file?


480

In una directory, ho un sacco di *.htmlfile. Vorrei rinominarli tutti in*.txt

Come lo posso fare? Uso la shell bash.

Risposte:


382

Per una soluzione migliore (con solo funzionalità bash, al contrario delle chiamate esterne), vedi una delle altre risposte .


Quanto segue farebbe e non richiede al sistema di avere il renameprogramma (anche se molto spesso lo avresti su un sistema):

for file in *.html; do
    mv "$file" "$(basename "$file" .html).txt"
done

EDIT: Come sottolineato nei commenti, questo non funziona per i nomi di file con spazi al loro interno senza una corretta citazione (ora aggiunta sopra). Quando lavori esclusivamente sui tuoi file che sai di non avere spazi nei nomi dei file, questo funzionerà ma ogni volta che scrivi qualcosa che può essere riutilizzato in un secondo momento, non saltare la citazione corretta.


47
Un'alternativa, senza basename e con virgolette: mv "$ {file}" "$ {file /%. Html / .txt}" (vedi man bash, Parameter Expansion per dettagli)
Rodrigo Queiro

7
Buono solo se i file sono tutti nella directory corrente, ovviamente, perché basename elimina la parte del percorso. Solo un 'attenzione'!
Jonathan Leffler,

6
Questa soluzione è negativa, non solo perché è lenta ma perché non funziona con nomi di file con spazi all'interno. Dovresti SEMPRE fare una citazione corretta negli script bash. mv "$ file" "$ (basename" $ ​​file ".html)". txt sarebbe molto meglio. Tuttavia, mv "$ files" "$ {files% .html} .txt" è molto meglio.
Balázs Pozsár il

8
nelle finestre che fairen *.a *.b
Muhammad Umer il

2
Come minimo, utilizzare la $()sintassi backtick specificata da POSIX anziché legacy. Migliora la leggibilità e rende la sintassi molto meno ambigua quando si hanno caratteri che dovrebbero essere sottoposti a backslash per essere letterali all'interno della sostituzione del comando con quest'ultimo.
Charles Duffy,

669

Se si utilizza bash, non sono necessari comandi esterni come sed, basename, rename, expr, ecc.

for file in *.html
do
  mv "$file" "${file%.html}.txt"
done

12
E se non conosci l'estensione del file che puoi usare "${file%.*}.txt", ma questo potrebbe essere pericoloso per i file senza estensione.
Jess,

1
Nota a chiunque abbia problemi a farlo funzionare come ho fatto io: nota che non ci sono $parentesi graffe all'interno!
doug65536

5
Ho bisogno di un modo per
aggiungere

7
@danip Il costrutto segno di percentuale all'interno della parentesi quadra i caratteri alla fine. Esiste anche un costrutto hash all'interno della parentesi che elimina i caratteri dall'inizio. Dai un'occhiata

4
Un'altra risposta di scambio di stack (che non riesco a trovare!) Ha suggerito questo, ma anche usando l ' --"operatore": mv - "$ file" "$ {file% .html} .txt" Quell'operatore impedisce i nomi di file che iniziano con un '-' dall'essere analizzato da mv come argomenti.
Rcreswick,

191
rename 's/\.html$/\.txt/' *.html

fa esattamente quello che vuoi.


Non penso che tu possa usare una regex letterale in bash come suggerisci tu - quale shell stai usando?
DaveR,

1
sto usando un terminale Mac
bmw0128

Ecco la pagina man per la versione di rinomina su Ubuntu: unixhelp.ed.ac.uk/CGI/man-cgi?rename
Amber

rinominare è un comando su alcuni sistemi. Ho una sceneggiatura Perl (originariamente dal primo libro di Camel) che fa il lavoro. C'è anche un programma GNU con lo stesso nome che fa più o meno lo stesso lavoro. Il mio Mac non ha un comando 'rinomina' fornito dal sistema - o non è sul mio PERCORSO (che è moderatamente completo).
Jonathan Leffler,

Esiste una formula di rinomina in Homebrew.
revprez,

112

Questo ha funzionato per me su OSX da .txt a .txt_bak

find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;

4
Funziona bene anche su Linux.
Diziet,

E 'questo il punto, ma per andare da .txta .txt_bakdevi solo concatenate _bak;)
corwin.amber

3
Questo è utile per rinominare in modo ricorsivo
leachryanb

Grande! (sotto Ubuntu 16.04) Il mio caso d'uso pratico, rinominando tutto .scssin .sass(dopo la conversione sul posto ...):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Frank Nocke

2
questo ha funzionato con +6000 file, la ridenominazione ha riportato che "l'elenco degli argomenti era troppo lungo"
Tony Cronin,

94

Vuoi usare rename:

rename -S .html .txt *.html

Questo fa esattamente quello che vuoi - cambierà l'estensione da .htmla .txtper tutti i file corrispondenti *.html.

Nota: Greg Hewgill sottolinea correttamente che questo non è un built-in bash; ed è un comando Linux separato. Se hai solo bisogno di qualcosa su Linux, questo dovrebbe funzionare bene; se hai bisogno di qualcosa di più multipiattaforma, dai un'occhiata a una delle altre risposte.


7
Sebbene questa sia una buona soluzione, il renameprogramma non è correlato bashe non è disponibile su tutte le piattaforme. L'ho visto solo su Linux.
Greg Hewgill,

15
"$ rename .html .txt * .html" genera ... errore di sintassi alla riga (eval 1) 1, vicino a "."
Ambra

8
La sintassi corretta è rename -S .html .text *.htmldove -Ssta per--subst-all
Marek Sebera

8
brew install rinomina
Nick

4
@GregHewgill rename è disponibile per Mac OS con HomeBrew
CodeBrauer



9

Questa è la soluzione più semplice che ho trovato che funziona su OSX e Linux, e funziona bene anche con Git!

find . -name "*.js" -exec bash -c 'mv "$1" "${1%.js}".tsx' - '{}' \;

e con git:

find . -name "*.js" -exec bash -c 'git mv "$1" "${1%.js}".tsx' - '{}' \;


8

Ecco un esempio del comando rename:

rename -n s/\.htm$/\.html/’ *.htm

-N significa che è un'esecuzione di prova e non cambierà alcun file. Ti mostrerà un elenco di file che verrebbero rinominati se rimossi -n. Nel caso sopra, convertirà tutti i file nella directory corrente da un'estensione di file .htm a .html.

Se l'output dell'esecuzione del test precedente sembrava corretto, è possibile eseguire la versione finale:

rename -v s/\.htm$/\.html/’ *.htm

-V è facoltativo, ma è una buona idea includerlo perché è l'unico record che avrai delle modifiche apportate dal comando rename come mostrato nell'output di esempio seguente:

$ rename -v 's/\.htm$/\.html/' *.htm
3.htm renamed as 3.html
4.htm renamed as 4.html
5.htm renamed as 5.html

La parte difficile nel mezzo è una sostituzione Perl con espressioni regolari, evidenziata di seguito:

rename -v s/\.htm$/\.html/’ *.htm

6

Questa domanda menziona esplicitamente Bash, ma se ti capita di avere ZSH disponibile è piuttosto semplice:

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

Se ottieni, zsh: command not found: zmvesegui semplicemente:

autoload -U zmv

E poi riprova.

Grazie a questo articolo originale per il suggerimento su zmv.


4

Dopo la scansione del sito Web di qualcun altro, ho trovato migliaia di file privi dell'estensione .html, in un ampio albero di sottodirectory.

Per rinominarli tutti in un colpo solo, tranne i file che hanno già un'estensione .html (molti di loro non ne avevano affatto), questo ha funzionato per me:

cd wwwroot
find . -xtype f \! -iname *.html   -exec mv -iv "{}"  "{}.html"  \;  # batch rename files to append .html suffix IF MISSING

Nel caso dell'OP, potrei modificarlo leggermente, per rinominare solo i file * .txt, in questo modo:

find . -xtype f  -iname *.txt   -exec filename="{}"  mv -iv ${filename%.*}.{txt,html}  \; 

Ripartito (hammertime!):

-iname * .txt
- Significa considerare SOLO i file che terminano già in .txt

mv -iv "{}. {txt, html}" - Quando find passa un {} come nome file, $ {nomefile%. *} estrae il nome base senza alcuna estensione per formare i parametri in mv . bash accetta {txt, html} per riscriverlo come due parametri, quindi il comando finale viene eseguito come:mv -iv "filename.txt" "filename.html"

Correzione necessaria però: gestione degli spazi nei nomi dei file


4

Il comandommv sembra svolgere questo compito in modo molto efficiente su un numero enorme di file (decine di migliaia in un secondo). Ad esempio, per rinominare tutti i .xmlfile in .htmlfile, utilizzare questo:

mmv ";*.xml" "#1#2.html"

il ;corrisponderà il percorso, il *corrisponderà il nome del file, e questi sono denominati #1e #2nel nome di sostituzione.

Le risposte basate su execo pipe erano troppo lente o non riuscivano su un numero molto elevato di file.


3

Prova questo

rename .html .txt *.html 

utilizzo:

rename [find] [replace_with] [criteria]

3

Un po 'in ritardo alla festa. Potresti farlo con xargs:

ls *.html | xargs -I {} sh -c 'mv $1 `basename $1 .html`.txt' - {}

O se tutti i tuoi file sono in qualche cartella

ls folder/*.html | xargs -I {} sh -c 'mv $1 folder/`basename $1 .html`.txt' - {}

3
No. Non analizzarels . Questo comando è ridicolo: usa inutilmente un glob con ls, invece di usare direttamente il glob. Ciò si interromperà con nomi di file contenenti spazi, virgolette e (a causa della mancanza di virgolette) caratteri glob.
gniourf_gniourf,

Cordiali saluti, il tuo articolo collegato contiene una nota aggiornata che dice che i nuovi file LS "scappano" correttamente se stampati sul terminale. " Il tuo punto è comunque una buona regola empirica.
Katastic Voyage,

3

Questo è un buon modo per modificare più estensioni contemporaneamente:

for fname in *.{mp4,avi}
do
   mv -v "$fname" "${fname%.???}.mkv"
done

Nota: fare attenzione alla dimensione dell'estensione per essere la stessa (???)


2

Bello e semplice!

find . -iname *.html  -exec mv {} "$(basename {} .html).text"  \;

2

Se preferisci PERL, c'è un breve script PERL (scritto originariamente da Larry Wall, il creatore di PERL) che farà esattamente quello che vuoi qui: tips.webdesign10.com/files/rename.pl.txt .

Per il tuo esempio, il trucco dovrebbe essere il seguente:

rename.pl 's/html/txt/' *.html

2
A questa domanda è già stata data risposta e accettata molto tempo fa e non sembra che la tua risposta porti qualcosa di più di quanto è già stato detto.
ChristopheLec,

1
+1 poiché era una sceneggiatura di Larry Wall (modificata da Robin Barker). L'ultimo URL disponibile è questo: tips.webdesign10.com/files/rename.pl.txt
loretoparisi

1

Analogamente a quanto suggerito prima, è così che l'ho fatto:

find . -name '*OldText*' -exec sh -c 'mv "$0" "${0/OldText/NewText}"' {} \;

Ho prima convalidato con

find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;

1

Una riga, nessun loop:

ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}

Esempio:

$ 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

+1 per mostrare un modo solo bash che non dipende dalla corrispondenza esatta dell'estensione esistente. Funziona con qualsiasi estensione di input, che si tratti di 3 caratteri lunghi o 4 caratteri lunghi o più
Ciprian Tomoiagă

0

Sfortunatamente non è banale fare in modo portabile. Probabilmente avrai bisogno di un po 'di magia expr.

for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done

Rimuovi l'eco quando sei felice fa quello che vuoi.

Modifica: basename è probabilmente un po 'più leggibile per questo caso particolare, sebbene exprsia più flessibile in generale.


Anche se questa potrebbe non essere la migliore risposta alla domanda, è stata per me! Avevo bisogno di un modo per rinominare solo in stringa un intero percorso, non solo il nome del file. Grazie per la pubblicazione!
Ciambella

0

Ecco cosa ho usato per rinominare i .edgefile.blade.php

for file in *.edge; do     mv "$file" "$(basename "$file" .edge).blade.php"; done

Funziona come il fascino.


0

Puoi anche fare una funzione in Bash, aggiungerla .bashrco qualcosa del genere e quindi usarla dove vuoi.

change-ext() {
    for file in *.$1; do mv "$file" "$(basename "$file" .$1).$2"; done
}

Uso:

change-ext css scss

Fonte del codice in funzione: https://stackoverflow.com/a/1224786/6732111


0

Rinomina le estensioni di file per tutti i file nella directory corrente e nelle sottodirectory senza altri pacchetti (usa solo script di shell):

  1. Creare uno script shell rename.shnella directory corrente con il seguente codice:

    #!/bin/bash
    
    for file in $(find . -name "*$1"); do
      mv "$file" "${file%$1}$2"
    done
  2. Eseguilo da ./rename.sh .old .new.

    Per esempio. ./rename.sh .html .txt

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.