Risposte:
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 rename
programma (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.
ren *.a *.b
$()
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.
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
"${file%.*}.txt"
, ma questo potrebbe essere pericoloso per i file senza estensione.
$
parentesi graffe all'interno!
--
"operatore": mv - "$ file" "$ {file% .html} .txt" Quell'operatore impedisce i nomi di file che iniziano con un '-' dall'essere analizzato da mv come argomenti.
rename 's/\.html$/\.txt/' *.html
fa esattamente quello che vuoi.
Questo ha funzionato per me su OSX da .txt a .txt_bak
find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;
.txt
a .txt_bak
devi solo concatenate _bak
;)
.scss
in .sass
(dopo la conversione sul posto ...):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Vuoi usare rename
:
rename -S .html .txt *.html
Questo fa esattamente quello che vuoi - cambierà l'estensione da .html
a .txt
per 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.
rename
programma non è correlato bash
e non è disponibile su tutte le piattaforme. L'ho visto solo su Linux.
rename -S .html .text *.html
dove -S
sta per--subst-all
Per utenti Ubuntu:
rename 's/\.html$/\.txt/' *.html
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
Questa domanda menziona esplicitamente Bash, ma se ti capita di avere ZSH disponibile è piuttosto semplice:
zmv '(*).*' '$1.txt'
Se ottieni, zsh: command not found: zmv
esegui semplicemente:
autoload -U zmv
E poi riprova.
Grazie a questo articolo originale per il suggerimento su zmv.
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
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 .xml
file in .html
file, utilizzare questo:
mmv ";*.xml" "#1#2.html"
il ;
corrisponderà il percorso, il *
corrisponderà il nome del file, e questi sono denominati #1
e #2
nel nome di sostituzione.
Le risposte basate su exec
o pipe erano troppo lente o non riuscivano su un numero molto elevato di file.
Prova questo
rename .html .txt *.html
utilizzo:
rename [find] [replace_with] [criteria]
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' - {}
ls
. 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.
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 (???)
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
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}"' {} \;
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
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 expr
sia più flessibile in generale.
Ecco cosa ho usato per rinominare i .edge
file.blade.php
for file in *.edge; do mv "$file" "$(basename "$file" .edge).blade.php"; done
Funziona come il fascino.
Puoi anche fare una funzione in Bash, aggiungerla .bashrc
o 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
Rinomina le estensioni di file per tutti i file nella directory corrente e nelle sottodirectory senza altri pacchetti (usa solo script di shell):
Creare uno script shell rename.sh
nella directory corrente con il seguente codice:
#!/bin/bash
for file in $(find . -name "*$1"); do
mv "$file" "${file%$1}$2"
done
Eseguilo da ./rename.sh .old .new
.
Per esempio. ./rename.sh .html .txt