Chcę zmienić nazwy wielu plików w tym samym katalogu za pomocą skryptów Bash. Nazwy plików są następujące:
file2602201409853.p file0901201437404.p file0901201438761.p file1003201410069.p file2602201410180.p
Chcę zmienić nazwę na następujący format:
file2503201409853.p file2503201437404.p file2503201438761.p file2503201410069.p file2503201410180.p
Czytałem o poleceniu rename i próbowałem to zrobić w ten sposób, ale nic nie robi, myślę, że mam pytania dotyczące składni. Następnie przeczytałem, że możesz utworzyć pętlę za pomocą polecenia mv w następujący sposób:
for file in cmpsms*2014*.p; do mv "$file" "${file/cmpsms*2014*.p/cmpsms25032014*.p}" done
Ale nie mogę zmienić nazw plików. Co robię źle?
Komentarze
Odpowiedź
Miałeś rację, rozważając najpierw zmianę nazwy. Składnia jest trochę dziwna, jeśli nie jesteś przyzwyczajony do wyrażeń regularnych, ale jest to zdecydowanie najszybsza / najkrótsza droga, gdy wiesz, co robisz:
rename "s/\d{4}/2503/" file*
To po prostu dopasowuje pierwsze 4 cyfry i zamienia je na te, które podałeś.
I testowa wiązka przewodów (-vn
oznacza być rozwlekłą, ale nie „t rób cokolwiek) używając nazw plików:
$ rename "s/\d{4}/2503/" file* -vn file0901201437404.p renamed as file2503201437404.p file0901201438761.p renamed as file2503201438761.p file1003201410069.p renamed as file2503201410069.p file2602201409853.p renamed as file2503201409853.p file2602201410180.p renamed as file2503201410180.p
Komentarze
- Uwaga że jest to zmiana nazwy Perla na Debianie i pochodnych (Ubuntu, Mint,…). W innych dystrybucjach Linuksa
rename
to zupełnie inne narzędzie do zmiany nazw plików (które Debian jest dostarczany jakorename.ul
). - Jeśli twój dystrybucyjny brak takiego narzędzia, spójrz na odpowiedź @Michael Campbell. Myślę, że każda dystrybucja zastąpi domyślną
rename
tak jak zrobił to debian.
Odpowiedź
To powinno załatwić sprawę:
for f in file*; do mv $f ${f/${f:4:8}/25032014}; done
Zastępuje ciąg między 4. a 12. znakiem „25032014”.
Komentarze
- to
for f in file*; do mv $f ${f/${f:4:4}/2503}; done
też działa. - That ' jest fajne. Jeśli chcesz użyć zwykłego słowa do zamiany słów, działa to jak sed. na przykład
for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
- @Eric – opublikowałem Twoją odpowiedź jako alternatywę, ponieważ myślę, że jest ona ' bardziej przejrzysta i elegancka . Jeśli chcesz również opublikować to jako odpowiedź – ' skasuję swoją. Dzięki!
- Dlaczego brakuje podwójnych cudzysłowów ?
- Występuje błąd: " mv: target ' FILE_NAME ' nie jest katalogiem "
Odpowiedź
to jest naprawdę odpowiedź @Erica z góry – ale to elegancka odpowiedź, więc Publikuję ponownie jako właściwą odpowiedź, aby zwrócić na nią więcej uwagi.
for f in *Huge*; do mv "$f" "${f/Huge/Monstrous}"; done
Odpowiedź
ptrn="file[0-9][0-9][0-9][0-9]2014[0-9][0-9][0-9][0-9][0-9].p" path=/dir ( set -- "${path}/"${ptrn} ; for f ; do { echo "mv ${path}/${f} \ ${path}/file25032014${f#2014}" } ; done )
To powinno załatwić sprawę. Uwaga – nie mam w zwyczaju przekazywać poleceń masowych mv – jak napisano, to tylko echo. Ty” Muszę to rozwiązać, zanim to zadziała.
Odpowiedź
Prosty natywny sposób na zrobienie tego bez zapętlania, z przeglądanie katalogu :
find -type f | xargs -I {} mv {} {}.txt
Będzie zmieniać nazwę co plik na miejscu.
A poniżej praca przykład z zrównolegleniem :
find -name "file*.p" | parallel "f="{}" ; mv -- {} ${f:0:4}2503${f:8}"
Komentarze
- Łatwo było wyobrazić sobie lepsze rozwiązanie. Jeśli chcesz, aby działało polecenie:
-
find -type f -name "file*.p" | parallel 'ext="{}" ; mv -- {} ${ext:0:4}2503${ext:8}'
Odpowiedz
Jeśli zauważysz, że często robisz takie rzeczy, wyszukaj „rename.pl”. Jest to skrypt w Perlu, ale pozwala po prostu przesłać go kodem Perla (jak /// wyrażenie) i dokona masowej zmiany nazwy na podstawie tego wyrażenia lub kodu.
Istnieje wersja podstawowa tutaj: http://stackoverflow.org/wiki/Rename.pl , ale po sieci krążą inne wersje. To istnieje od wieków, od wieków i od wieków.
*
jest?