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ł renameprogram (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"' {} \;
.txtaby .txt_bakpo prostu mieć do łączenia _bak;)
.scssna .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 .htmlna .txtdla 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.
renameprogram nie jest powiązany bashi nie jest dostępny na wszystkich platformach. Widziałem to tylko w systemie Linux.
rename -S .html .text *.htmlgdzie -Soznacza--subst-all
Na komputerze Mac ...
brew install renamerename -S .html .txt *.htmlDla 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: zmvpo 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 .xmlplików na .htmlpliki, użyj tego:
mmv ";*.xml" "#1#2.html"
;będzie pasował do ścieżki, *będzie pasował do nazwy pliku, a te są nazywane #1i #2w nazwie zastępczej.
Odpowiedzi na podstawie execlub 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 lszamiast 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ż exprogólnie jest bardziej elastyczna.
Oto, do czego zmieniałem nazwy .edgeplikó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ą .bashrclub 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.shw bieżącym katalogu z następującym kodem:
#!/bin/bash
for file in $(find . -name "*$1"); do
mv "$file" "${file%$1}$2"
doneUruchom to ./rename.sh .old .new.
Na przykład. ./rename.sh .html .txt