rekurencyjnie dodaj rozszerzenie pliku do wszystkich plików


106

Mam kilka katalogów i podkatalogów zawierających pliki bez rozszerzenia. Chcę dodać .jpgdo wszystkich plików zawartych w tych katalogach. Widziałem skrypty bash do zmiany rozszerzenia pliku, ale nie tylko do dodania jednego. Musi też być rekurencyjna, czy ktoś może mi pomóc?

Odpowiedzi:


228

Alternatywne polecenie bez jawnej pętli ( man find):

find . -type f -exec mv '{}' '{}'.jpg \;

Objaśnienie: to rekurencyjnie wyszukuje wszystkie pliki ( -type f), zaczynając od bieżącego katalogu ( .) i stosuje polecenie move ( mv) do każdego z nich. Zwróć również uwagę na cudzysłowy {}, aby nazwy plików ze spacjami (a nawet znakami nowej linii ...) były prawidłowo obsługiwane.


7
W szczególności ten działa lepiej, jeśli w strukturze katalogów jest ogromna liczba plików (powodując, że bash denerwuje się długością listy plików do iteracji).
DrAl,

@Al, jeśli odwołujesz się do forpętli denerwującej bash, aby iterować po liście plików, to nie jest poprawne. forPętla bash iteracyjnie wydaje każde mvpolecenie.
nik,

Pytanie: Czy findnajpierw tworzy listę plików przed wykonaniem -execinstrukcji? Chyba tak, ale chcę wyjaśnić ten punkt przed zakodowaniem nieskończonych pętli.
Boldewyn

2
to polecenie znajdzie również pliki z rozszerzeniem. Czy tego chce OP?
ghostdog74

1
@ ghostdog74: Ponieważ przyjął tę odpowiedź, powyższe najwyraźniej załatwiło sprawę. W przeciwnym razie, jak wspomniałeś poniżej, dodanie -not -name "*.*"wystarczy.
Stephan202,

62

to znajdzie pliki bez rozszerzenia i doda twój .jpg

find /path -type f -not -name "*.*" -exec mv "{}" "{}".jpg \;

To z pewnością zapewni pożądany rezultat w 99% przypadków. +1
les

9

Trochę za późno, ale pomyślałem, że dodam, że lepszym rozwiązaniem (choć może mniej czytelnym) od dotychczasowych mogłoby być:

find /path -type f -not -name "*.*" -print0 | xargs -0 rename 's/(.)$/$1.jpg/'

Użycie find | xargswzorca generalnie skutkuje bardziej wydajnym wykonaniem, ponieważ nie trzeba rozwidlać nowego procesu dla każdego pliku.

Zauważ, że wymaga to wersji zmiany nazwy, którą można znaleźć w dystrybucjach o smaku Debiana (zwanej również prename), a nie tradycyjnej zmiany nazwy. Jest to jednak tylko mały skrypt w Perlu, więc byłoby dość łatwo użyć powyższego polecenia w dowolnym systemie.


4

lubię to,

for f in $(find . -type f); do mv $f ${f}.jpg; done

Nie spodziewam się, że będziesz mieć nazwy plików oddzielone spacjami.
Jeśli to zrobisz, nazwy będą musiały zostać nieco przetworzone.

Jeśli chcesz, aby wykonać polecenie z jakiegoś innego katalogu,
można wymienić find .z find /target/directory.


1
Brakuje „do” i jeśli w nazwie pliku znajdują się spacje, lepiej będzie cytować nazwę pliku: for f in $ (find. -Type f); do mv "$ f" "$ {f} .jpg"; gotowe
DrAl

i prawdopodobnie uruchomiłbym to z katalogu najwyższego poziomu?
robjmills

@seengee: tak. Zwróć uwagę, że to polecenie pomija również myślnik -type.
Stephan202,

Musiałem gdzieś iść i pisać za szybko ... naprawianie teraz.
nik,

1

Aby zmienić nazwę wszystkich plików bez rozszerzenia w systemie Windows Basic, możesz to zrobić ren * *.jpg Ponieważ plik nie ma rozszerzenia, po prostu użyj *, lub jeśli chcesz zmienić png na jpg użyjren *.png *.jpg


0

rename

nie jestem pewien, czy może zmienić nazwy plików bez rozszerzeń (jestem teraz w systemie Windows 7)


1
tak, ale zmieni również nazwy katalogów i nie ma sposobu, aby nakazać mu rekurencyjną pracę w podkatalogach (przynajmniej z wersją, którą mam na Ubuntu).
mirod

Znam co najmniej dwa różne polecenia o nazwie rename, jeden program w C zawarty w util-linux-ng i jeden program w Perlu (autorstwa samego Wall'a) na komputerach Debiana naszego uniwersytetu. W rzeczywistości żaden z nich nie wykonuje rekursji.
Boldewyn
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.