Odpowiedzi:
Aby uzyskać lepsze rozwiązanie (tylko z funkcją bash, w przeciwieństwie do połączeń zewnętrznych), zobacz jedną z pozostałych odpowiedzi .
Następujące czynności zrobiłyby i nie wymagają, aby system miał rename
program (chociaż najczęściej miałbyś to w systemie):
for file in *.html; do
mv "$file" "$(basename "$file" .html).txt"
done
EDYCJA: Jak wskazano w komentarzach, nie działa to dla nazw plików ze spacjami bez odpowiedniego cytowania (teraz dodanego powyżej). W przypadku pracy wyłącznie na własnych plikach, o których wiesz, że w nazwach plików nie ma spacji, będzie to działać, ale ilekroć napiszesz coś, co może być ponownie wykorzystane później, nie pomijaj właściwego cytowania.
ren *.a *.b
$()
zamiast starszej składni backtick. Poprawia czytelność i sprawia, że składnia jest znacznie mniej dwuznaczna, gdy masz znaki, które musiałyby być poprzedzone odwrotnym ukośnikiem, aby były dosłowne wewnątrz podstawienia polecenia tym ostatnim.
Jeśli używasz bash, nie potrzebujesz zewnętrznych poleceń, takich jak sed, basename, zmiana nazwy, wyrażenie itp.
for file in *.html
do
mv "$file" "${file%.html}.txt"
done
"${file%.*}.txt"
, może to być niebezpieczne dla plików bez rozszerzenia.
$
w nawiasach klamrowych nie ma nic !
--
„operatora”: mv - „$ plik” „$ {plik% .html} .txt” Ten operator zapobiega nazwom plików rozpoczynającym się od a - - z parsowania przez mv jako argumentów.
rename 's/\.html$/\.txt/' *.html
robi dokładnie to, co chcesz.
To działało dla mnie w OSX od .txt do .txt_bak
find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;
.txt
aby .txt_bak
po prostu mieć do łączenia _bak
;)
.scss
na .sass
(po konwersji w miejscu…):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Chcesz użyć rename
:
rename -S .html .txt *.html
To robi dokładnie to, co chcesz - zmieni to rozszerzenie z .html
na .txt
dla wszystkich pasujących plików *.html
.
Uwaga: Greg Hewgill poprawnie wskazuje, że nie jest to wbudowane bash; i jest osobnym poleceniem Linuksa. Jeśli potrzebujesz czegoś w systemie Linux, powinno to działać poprawnie; jeśli potrzebujesz czegoś więcej na różnych platformach, spójrz na jedną z pozostałych odpowiedzi.
rename
program nie jest powiązany bash
i nie jest dostępny na wszystkich platformach. Widziałem to tylko w systemie Linux.
rename -S .html .text *.html
gdzie -S
oznacza--subst-all
Na komputerze Mac ...
brew install rename
rename -S .html .txt *.html
Dla użytkowników Ubuntu:
rename 's/\.html$/\.txt/' *.html
Oto przykład polecenia zmiany nazwy:
rename -n ’s/\.htm$/\.html/’ *.htm
-N oznacza, że jest to uruchomienie testowe i tak naprawdę nie zmieni żadnych plików. Wyświetli ci listę plików, których nazwy można zmienić, jeśli usuniesz -n. W powyższym przypadku skonwertuje wszystkie pliki w bieżącym katalogu z rozszerzenia .htm na .html.
Jeśli wynik powyższego uruchomienia testowego wyglądał dobrze, możesz uruchomić ostateczną wersję:
rename -v ’s/\.htm$/\.html/’ *.htm
Opcja -v jest opcjonalna, ale warto ją uwzględnić, ponieważ jest to jedyny rekord, w którym będziesz mieć zmiany dokonane za pomocą polecenia rename, jak pokazano w przykładowym wyniku poniżej:
$ rename -v 's/\.htm$/\.html/' *.htm
3.htm renamed as 3.html
4.htm renamed as 4.html
5.htm renamed as 5.html
Trudna część pośrodku to podstawienie Perla wyrażeniami regularnymi, podkreślone poniżej:
rename -v ’s/\.htm$/\.html/’ *.htm
To pytanie wyraźnie wspomina o Bash, ale jeśli zdarzy ci się mieć ZSH, jest to dość proste:
zmv '(*).*' '$1.txt'
Jeśli otrzymasz, zsh: command not found: zmv
po prostu uruchom:
autoload -U zmv
A potem spróbuj ponownie.
Dzięki temu oryginalnemu artykułowi na wskazówkę o zmv.
Po zaindeksowaniu czyjejś witryny internetowej skończyło się to tym, że tysiące plików nie ma rozszerzenia .html w szerokim drzewie podkatalogów.
Aby zmienić nazwę wszystkich w jednym ujęciu, z wyjątkiem plików, które mają już rozszerzenie .html (większość z nich w ogóle nie miała), działało to dla mnie:
cd wwwroot
find . -xtype f \! -iname *.html -exec mv -iv "{}" "{}.html" \; # batch rename files to append .html suffix IF MISSING
W przypadku OP mogę to nieco zmodyfikować, aby zmienić tylko nazwy plików * .txt, tak jak poniżej:
find . -xtype f -iname *.txt -exec filename="{}" mv -iv ${filename%.*}.{txt,html} \;
W podziale (hammertime!):
-iname * .txt
- oznacza, że uwzględniają TYLKO pliki, które kończą się na .txt
mv -iv "{}. {txt, html}" - Gdy find podaje {} jako nazwę pliku, $ {nazwa_pliku%. *} wyodrębnia swoją nazwę basename bez żadnego rozszerzenia, aby utworzyć parametry dla mv . bash bierze {txt, html}, aby przepisać go jako dwa parametry, więc końcowe polecenie działa jako:mv -iv "filename.txt" "filename.html"
Niezbędna poprawka: radzenie sobie ze spacjami w nazwach plików
Poleceniammv
wydaje się bardzo sprawnie wykonać to zadanie na ogromną liczbę plików (dziesiątki tysięcy na sekundę). Na przykład, aby zmienić nazwę wszystkich .xml
plików na .html
pliki, użyj tego:
mmv ";*.xml" "#1#2.html"
;
będzie pasował do ścieżki, *
będzie pasował do nazwy pliku, a te są nazywane #1
i #2
w nazwie zastępczej.
Odpowiedzi na podstawie exec
lub potoki były zbyt wolne lub nie powiodły się w przypadku bardzo dużej liczby plików.
Spróbuj tego
rename .html .txt *.html
stosowanie:
rename [find] [replace_with] [criteria]
Trochę późno na imprezę. Możesz to zrobić za pomocą xargs:
ls *.html | xargs -I {} sh -c 'mv $1 `basename $1 .html`.txt' - {}
Lub jeśli wszystkie twoje pliki są w jakimś folderze
ls folder/*.html | xargs -I {} sh -c 'mv $1 folder/`basename $1 .html`.txt' - {}
ls
. To polecenie jest niedorzeczne: bezużytecznie używa globu z ls
zamiast globalnego użycia globusa. Spowoduje to zerwanie nazw plików zawierających spacje, cytaty i (z powodu braku cytatów) znaków globalnych.
To dobry sposób na modyfikację wielu rozszerzeń jednocześnie:
for fname in *.{mp4,avi}
do
mv -v "$fname" "${fname%.???}.mkv"
done
Uwaga: uważaj, aby rozmiar rozszerzenia był taki sam (???)
Jeśli wolisz PERL, istnieje krótki skrypt PERL (pierwotnie napisany przez Larry'ego Walla, twórcę PERL), który zrobi dokładnie to, co chcesz tutaj: tips.webdesign10.com/files/rename.pl.txt .
W twoim przykładzie należy wykonać następujące czynności:
rename.pl 's/html/txt/' *.html
Podobnie jak wcześniej zasugerowano, tak to zrobiłem:
find . -name '*OldText*' -exec sh -c 'mv "$0" "${0/OldText/NewText}"' {} \;
Najpierw zatwierdziłem
find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;
Jedna linia, bez pętli:
ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
Przykład:
$ 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
Niestety nie jest to łatwe do przenoszenia. Prawdopodobnie potrzebujesz odrobiny magii expr.
for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done
Usuń echo, gdy będziesz zadowolony, że zrobi to, co chcesz.
Edycja: basename
jest prawdopodobnie nieco bardziej czytelna w tym konkretnym przypadku, chociaż expr
ogólnie jest bardziej elastyczna.
Oto, do czego zmieniałem nazwy .edge
plików.blade.php
for file in *.edge; do mv "$file" "$(basename "$file" .edge).blade.php"; done
Działa jak urok.
Możesz także utworzyć funkcję w Bash, dodać ją .bashrc
lub coś, a następnie użyć jej w dowolnym miejscu.
change-ext() {
for file in *.$1; do mv "$file" "$(basename "$file" .$1).$2"; done
}
Stosowanie:
change-ext css scss
Źródło kodu w funkcji: https://stackoverflow.com/a/1224786/6732111
Zmień nazwy rozszerzeń plików dla wszystkich plików w bieżącym katalogu i podkatalogach bez żadnych innych pakietów (użyj tylko skryptu powłoki):
Utwórz skrypt powłoki rename.sh
w bieżącym katalogu z następującym kodem:
#!/bin/bash
for file in $(find . -name "*$1"); do
mv "$file" "${file%$1}$2"
done
Uruchom to ./rename.sh .old .new
.
Na przykład. ./rename.sh .html .txt