Zmień nazwę grupy plików za pomocą jednego polecenia

38

Jeśli mam grupę plików z rozszerzeniem .htm, jak mogę zmienić ich nazwy na .html?

mv *.htm *.html

nie działa.

Richard Hoskins
źródło
Tylko ze względu na kompletność, ren *.htm *.htmlbędzie działać w systemie Windows.
Brian Burns

Odpowiedzi:

50

Lub możesz użyć czystej bash ... (oprócz mv, to znaczy ...)

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

i unikaj nieprzyjemnych rzeczy basename. ;)

Bash ma bogaty zestaw zmiennych opcji ekspansji. Zastosowany tutaj „%” usuwa najmniejszy zgodny sufiks z wartości zmiennej. Wzór jest wzorem globalnym, więc ${file%.*}też by działał. Operator „%%” usuwa największy pasujący sufiks i jest wymienny w powyższym przykładzie, ponieważ wzorzec jest ustalony, ${file%%.*}.htmlzmieniłby abhtm w a.html.

Zobacz sekcję zmiennego podstrona strony podręcznika bash, aby uzyskać więcej schludnych sztuczek. Jest wiele rzeczy, które można zrobić bezpośrednio w bash.

falstro
źródło
1
Zauważ też, że te rozszerzenia parametrów nie są ograniczone do bash . Są one dostępne na wszystkich powłokach Bourne'a ( sh , ksh , bash , zsh , dash , ash itp.). Rozszerzenia są częścią specyfikacji POSIX dla „Shell Command Language” i są wysoce przenośne.
Chris Johnsen
11

W nazwach plików nie powinno być spacji, znaków nowej linii ani innych białych znaków, ale ta wersja odpowiedzi freiheit obsługuje je. Używa również $()zamiast backticks dla czytelności wraz z innymi korzyściami.

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

Jeszcze lepiej - w specjalnym przypadku dodawania tylko do końca:

for file in *.htm
do
    mv "$file" "${file}l"
done
Wstrzymano do odwołania.
źródło
11

rename(1)to narzędzie Perla, które robi dokładnie to, co chcesz. W tym przypadku:

rename 's/\.htm$/.html/' *htm

lub jeśli używasz również podkatalogów

(wymaga Bash 4.0 i ustawienie globstar: shopt -s globstar)

rename 's/\.htm$/.html/' **/*htm

TRS-80
źródło
1
zmiana nazwy jest łatwiejsza, ale nie jest standardowym programem uniksowym; oryginalne pytanie nie określa, który unix. W niektórych miejscach wydaje się być „prename”.
freiheit,
2
renamepochodzi z perla, i w zasadzie każdy unix ma teraz perla.
TRS-80,
3
tak, ale nie każdy uniks zawiera programy pomocnicze, takie jak „zmiana nazwy”, kiedy wprowadzają perla do systemu. Na przykład w OSX nie ma „zmiany nazwy”.
freiheit
1
@William: Składnia podwójnej gwiazdki jest dostępna tylko w Bash 4 i nowszych wersjach i tylko wtedy, gdy jest włączona shopt -s globstar(domyślnie wyłączona). Ponadto Linux i Unix mają katalogi zamiast folderów.
Wstrzymano do odwołania.
6
for file in *.htm; do
  mv $file `basename "$file" .htm`.html
done

Wypróbuj go ze związkiem echoprzed mvpierwszym razem.

Problem z oryginałem polega na tym, że „ mv *.htm *.html” ma *s obsługiwane przez powłokę, więc mvpolecenie po prostu wyświetla listę wszystkich plików .htm i .html w bieżącym katalogu. Innymi słowy, coś w stylu „ mv foo.htm bar.htm stuff.htm six.htm file.htm”. mv wie, jak obsługiwać więcej niż 2 argumenty, jeśli ostatni jest katalogiem.

freiheit
źródło
1
Powinieneś zacytować „$ file”, aby obsłużyć spacje.
Richard Hoskins,
Twój opis pierwotnego problemu powinien być silniej podkreślony. To zachowanie interpretacji symboli wieloznacznych powłoki jest zaskakujące i nie jest intuicyjne dla kogoś pochodzącego z systemu Windows, a zrozumienie tego, co robi powłoka, wyjaśnia, dlaczego oryginalna aplikacja mvnie działa.
Greg Hewgill
3

Jeszcze inny przykład czystego basha z użyciem metody replace łańcucha.

for file in *.htm; do mv $file ${file/htm/html}; done

Extra - zastępuje wszystkie wystąpienia ciągu

for file in *.htm; do mv $file ${file//htm/html}; done
Xalupadas
źródło
1

Jeśli używasz Zsh , możesz użyć „zmv”

Jaskółka oknówka
źródło
1

Najlepszym narzędziem jest mmv .

mmv \*.htm #1.html

Inne przykłady użycia (i innych narzędzi) w „ Podsumowaniu narzędzi wiersza poleceń GNU / Linux ”.

bortzmeyer
źródło
1
Twój przykład użycia kończy się niepowodzeniem. Musisz uciec #.
Cristian Ciupitu,
Nie, to działa (ZAWSZE testuję przed opublikowaniem na SuperUser). Konieczność ucieczki # zależy od używanej powłoki (używam zsh).
bortzmeyer
0

Pakiet util-linux-ng (w Fedorze) ma renamepolecenie podobne do polecenia wspomnianego przez TRS-80 . Możesz użyć tego w następujący sposób:

rename .htm .html *.html
Cristian Ciupitu
źródło