Jak zmienić rozszerzenie wielu plików?


166

Chciałbym zmienić rozszerzenie pliku z *.txtna *.text. Próbowałem użyć basenamepolecenia, ale mam problem ze zmianą więcej niż jednego pliku.

Oto mój kod:

files=`ls -1 *.txt`

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

Otrzymuję ten błąd:

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

Odpowiedzi:


175

Prosto z Wiki Grega :

# Zmień nazwę wszystkich * .txt na * .text
dla f w * .txt; zrobić
    mv - "$ f" "$ {f% .txt} .text"
gotowy

Zobacz także wpis, dlaczego nie powinieneś analizowaćls .

Edycja: jeśli musisz użyć basenameskładni, należy:

dla f w * .txt; zrobić
    mv - "$ f" "$ (basename -" $ f ".txt) .text"
gotowy

48
Użyto tutaj nieco zaawansowanej składni Bash bez wyjaśnienia. Musiałem Google wiele rzeczy, aby w pełni to zrozumieć. Aby pomóc innym w mojej pozycji, oto kilka odniesień na temat globów ( *.txtskładnia) , gołej podwójnej kreski-- i użycia symbolu% w ${}konstrukcie . Do tej pory nigdy nie spotkałem dwóch ostatnich i nie wiedziałem, co tak naprawdę dzieje się z tym pierwszym.
Mark Amery

3
Spójrz na odpowiedź Matthiasa Brauna poniżej - znacznie prościej, osiąga to samo.
btk

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

1
Brakuje ci; po tekście ".
Pétur Ingi Egilsson

2
@ PéturIngiEgilsson w drugiej linii? Nie, nie jest to wymagane.
jasonwryan

132

Oto jak zmieniam wszystkie rozszerzenia plików w bieżącym katalogu Debiana.

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

(To jest renamepolecenie Perla , a nie util-linuxjedno. Zobacz Dlaczego narzędzie zmiany nazwy w Debian / Ubuntu różni się od tego w innych dystrybucjach, takich jak CentOS? )


10
O wiele prostsze niż zaakceptowana odpowiedź, dziękuję!
btk

8
Na Macu mogłem to brew install renamezrobić.
Monkpit,

3
za pomocą skorupy ryby możesz zrobić, rename "s/oldExtension/newExtension/" **.txtaby zmienić nazwę wszystkich * .txt rekurencyjnie
Palmstrom

3
To się nie powiedzie footxt.txt. Zamiast tego użyj tego: unix.stackexchange.com/questions/19654/…
wisbucky

7
Kiedy twoje pliki nie mają żadnego rozszerzenia i chcesz je dodać:rename 's/$/.txt/' *
mkataja

34

To proste polecenie, renamefromutil-linux , zrobi to za Ciebie, zamieni każde wystąpienie „txt” na „text” we wszystkich plikach pasujących do „* .txt”:

rename txt text *.txt

4
renamezmienia pierwsze wystąpienie, więc lepiej zrobić to rename .txt .text, ale to jeszcze nie zawsze będzie działać (na przykład, że zmienia nazwę foo.txtx.bar.txtna foo.textx.bar.txt).
Gilles

12
Należy zauważyć, że nie wszystkie systemy mają tę samą wersję zmiany nazwy; na Debianie i przyjaciołach renamepolecenie jest w rzeczywistości perl-renamei używa wyrażeń regularnych perla. Za to odpowiednik polecenia będzie: rename 's/.txt/.text/' *.txt. Ludzie powinni sprawdzić man renamew swoim systemie, aby dowiedzieć się, który mają.
evilsoup

@evilsoup Tak jest w przypadku OSX, dzięki
Davi Lima

Działa to również w Cygwin (Windows)
andy

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

Powyżej działa dobrze, ale ogranicza się do bieżącego katalogu. Wypróbuj poniższe polecenie, które jest elastyczne w przypadku podkatalogów. Zmieni nazwę wszystkich .txtplików w strukturze katalogów z nowym rozszerzeniem.

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

2
renamepotrafi obsłużyć wiele plików jako argument, możesz znacznie przyspieszyć, używając +zamiast tego, \;jeśli jest wiele takich plików
Anthon

Jest to jednak przydatna opcja, ponieważ „* .txt” może rozwinąć się do dużej listy argumentów nieobsługiwanej przez powłokę.
Roman Shapovalov,

1
Błąd „s / oldExtension / newExtension /” nie powiedzie się footxt.txt. Zamiast tego użyj tego: unix.stackexchange.com/questions/19654/…
wisbucky


9

Odpowiedzi tutaj odnoszące się s/oldExtension/newExtension/są błędne. Jeśli użyjesz s/txt/text/, przekonwertujesz footxt.txtna footext.txt, co nie jest tym, czego chcesz. Nawet jeśli użyjesz s/.txt/.text/, to przekonwertuje się footxt.txtna fo.text.txt.

Musisz użyć, \.aby dopasować okres ( .pasuje do dowolnej postaci). I końcowe, $aby dopasować do końca linii. Tylko to będzie poprawnie pasowało do rozszerzenia.

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

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

7

W oparciu o odpowiedź @Prince John Wesley, oto prosty skrypt bash do zmiany wszystkich rozszerzeń plików w bieżącym katalogu z ext1na ext2. Wyświetla również nazwy plików, których nazwy są zmieniane.

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

Przykładowe użycie (przy założeniu, że nazwa skryptu to change-ext):

change-ext ext1 ext2

Aby rekurencyjnie zmieniać rozszerzenia plików w katalogach, zamień drugą linię ( for...) na dwie linie: shopt -s globstari for f in **/*.$1. Wymaga Bash 4+.
Dennis Golomazov


3

powiedzmy, że twoje pliki są rozproszone w różnych katalogach. Zakładając, że dirx jest katalogiem nadrzędnym, można to zrobić za pomocą find:

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

Co z tcsh ..
Josef Klimuk


2

Kiedy ty

nie mają rozszerzenia dla plików źródłowych

a celem docelowym jest .text , zrobiłbyś to w ten sposób -

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

1
Doskonały skrypt bash-native. działało świetnie! for f in *.html; do mv -- "$f" "${f%.\*}.pug"; done
TamusJRoyce

1

Jeśli chcesz wiedzieć, co poszło nie tak w twojej wersji: Użyłeś $fileszamiast $xw poleceniu basename. Powinno to działać (choć nie przetestowane):

for x in *.txt
do
  mv "$x" "`basename '$x' .txt`.text"
done
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.