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.