Muszę zmienić nazwę ok. 70 000 plików. Na przykład: Od sb_606_HBO_DPM_0089000
do sb_606_dpm_0089000
itp.
Zakres liczb wynosi od 0089000
do 0163022
. To tylko pierwsza część nazwy, która musi się zmienić. wszystkie pliki znajdują się w jednym katalogu i są kolejno ponumerowane (sekwencja obrazów). Liczby muszą pozostać niezmienione.
Kiedy próbuję tego w bash, dręczy mnie, że „lista argumentów jest za długa”.
Edytować:
Najpierw próbowałem zmienić nazwę pojedynczego pliku za pomocą mv
:
mv sb_606_HBO_DPM_0089000.dpx sb_606_dpm_0089000.dpx
Potem próbowałem zmienić nazwę zakresu (w zeszłym tygodniu nauczyłem się tutaj, jak przenosić ładunek plików, więc pomyślałem, że ta sama składnia może działać do zmiany nazw plików ...). Myślę , że próbowałem następujące (lub coś podobnego):
mv sb_606_HBO_DPM_0{089000..163023}.dpx sb_606_dpm_0{089000..163023}.dpx
command-line
bash
batch-rename
bogaty
źródło
źródło
ARG_MAX
limitem powłoki . Ponieważ pytanie to wyraźnie wymaga rozwiązania z wiersza poleceń, (prawdopodobnie równe) rozwiązania GUI, tak jak w drugim pytaniu, również się nie zgadzają.mv {1..2} {3..4}
nie działa, co jest zupełnie innym problemem niżARG_MAX
... Każdy, kto odpowiedział, prawdopodobnie poczuje to samo! Tak więc, z mojego punktu widzenia, chciałbym, żebyś cofnął swoją ostatnią edycję i, jeśli chcesz, zadałby zupełnie nowe pytanie dotyczącemv
ing z zakresamiargument list too long
błąd. Nie ma potrzeby dalszego wyjaśniania, to oczywiście nie jest duplikat, ponieważ potrzebujemy obejścia problemu z ARG_MAX, a odpowiedzi w proponowanym duplikacie tego nie robią.Odpowiedzi:
Jednym ze sposobów jest skorzystanie
find
z-exec
oraz+
opcji. Tworzy to listę argumentów, ale dzieli listę na tyle wywołań, ile potrzeba do działania na wszystkich plikach bez przekraczania maksymalnej listy argumentów. Jest odpowiedni, gdy wszystkie argumenty będą traktowane tak samo. Tak jest w przypadkurename
, choć nie w przypadkumv
.Może być konieczne zainstalowanie zmiany nazwy Perla:
Następnie możesz użyć na przykład:
Usuń
-n
po przetestowaniu, aby faktycznie zmienić nazwę plików.źródło
Mam zamiar zasugerować trzy alternatywy. Każde z nich jest prostym poleceniem w jednym wierszu, ale podam warianty dla bardziej skomplikowanych przypadków, głównie na wypadek, gdyby pliki do przetworzenia zostały zmieszane z innymi plikami w tym samym katalogu.
mmv
Chciałbym użyć polecenia MMV z pakietu o tej samej nazwie :
Zauważ, że argumenty są przekazywane jako ciągi, więc ekspansja globu nie zachodzi w powłoce. Polecenie otrzymuje dokładnie dwa argumenty, a następnie wyszukuje odpowiednie pliki wewnętrznie, bez ścisłych ograniczeń liczby plików. Zauważ też, że powyższe polecenie zakłada, że wszystkie pliki pasujące do pierwszego globu zostaną przemianowane. Oczywiście możesz być bardziej szczegółowy:
Jeśli pliki znajdują się poza żądanym zakresem numerów w tym samym katalogu, lepiej byłoby, gdyby pętla nad liczbami była podana w dalszej części tej odpowiedzi. Można jednak użyć sekwencji wywołań mmv z odpowiednimi wzorami:
zapętlić liczby
Jeśli chcesz uniknąć instalowania czegokolwiek lub musisz wybrać według zakresu numerów, unikając dopasowań poza tym zakresem, i jesteś gotowy czekać na 74.023 wywołania komend, możesz użyć zwykłej pętli bash:
Działa to szczególnie dobrze, ponieważ nie ma żadnych przerw w sekwencji. W przeciwnym razie możesz sprawdzić, czy plik źródłowy faktycznie istnieje.
Zauważ, że w przeciwieństwie do
for ((i=89000; i<=163022; ++i))
rozszerzenia nawiasów obsługuje zer wiodących, ponieważ kilka wersji Bash kilka lat temu. Właściwie o zmianę, o którą prosiłem, więc cieszę się, że widzę przypadki jej użycia.Dalsza lektura: Brace Expansion na stronach informacyjnych Bash, szczególnie w części o
{x..y[..incr]}
.przeglądaj pliki
Inną opcją byłoby zapętlenie odpowiedniego globu zamiast zapętlenia danego zakresu liczb całkowitych. Coś takiego:
Ponownie jest to jedno
mv
wywołanie na plik. I znowu pętla ma długą listę elementów, ale cała lista nie jest przekazywana jako argument do podprocesu, ale obsługiwana wewnętrznie przez bash, więc limit nie spowoduje problemów.Dalsza lektura: Rozszerzanie parametrów powłoki na stronach informacyjnych Bash, dokumentowanie
${parameter/pattern/string}
między innymi.Jeśli chcesz ograniczyć zakres numerów do tego, który podałeś, możesz dodać opcję:
Tutaj
${i##pattern}
usuwa najdłuższe dopasowanie prefiksupattern
z$i
. Ten najdłuższy prefiks jest zdefiniowany jako dowolny, następnie znak podkreślenia, a następnie zero lub więcej zer. Ten ostatni jest zapisywany jako taki,*(0)
który jest rozszerzonym wzorcem globu, który zależy od ustawionejextglob
opcji . Usuwanie zer wiodących jest ważne, aby traktować liczbę jako bazę 10, a nie 8. Argument+([0-9])
w pętli to kolejny rozszerzony glob, dopasowujący jedną lub więcej cyfr, na wypadek, gdyby pliki tam, które zaczynają się tak samo, ale nie kończą się na numer.źródło
Jednym ze sposobów obejścia tego
ARG_MAX
ograniczenia jest użycie wbudowanej powłoki bashprintf
:Dawny.
ale
źródło
find
w bieżącym katalogu.
dla wszystkich plików-type f
i zmień nazwę znalezionego pliku,$1
zastępującHBO_DPM
godmp
jeden po drugim-exec ... \;
wymienić
echo
zemv
wykonać polecenie Zmień nazwę.źródło
Możesz napisać mały skrypt Pythona, taki jak:
Zapisz to jako plik tekstowy, tak jak
rename.py
w folderze, w którym znajdują się pliki, a następnie z terminalem w tym folderze przejdź:źródło
Możesz to zrobić plik po pliku (może to zająć trochę czasu)
Podobnie jak Perl
rename
używany w innych odpowiedziach,rename.ul
ma również opcję-n
lub--no-act
do testowania.źródło
-n
flagi, której użyłem do testowania i sugerował, że można jej również użyćrename.ul
.Widzę, że nikt nie zaprosił mojego najlepszego przyjaciela
sed
na imprezę :). Następującefor
pętla osiągnie twój cel:Istnieje wiele narzędzi do takiej pracy, wybierz najbardziej zrozumiałe dla Ciebie. Ten jest prosty i łatwo go zmienić, aby pasował do tego lub innych celów ...
źródło
$i
w podstawieniu polecenia, ale nie jest to łatwy sposób na obsługę końcowego znaku nowej linii w nazwie pliku.Ponieważ dajemy opcje, oto podejście Perla.
cd
do katalogu docelowego i uruchom:Wyjaśnienie
perl -e
: uruchom skrypt podany przez-e
.foreach(glob){}
: uruchom cokolwiek{ }
na każdym wyniku globu.glob("sb_*")
: zwraca listę wszystkich plików i katalogów w bieżącym katalogu, których nazwy pasują do globu powłokisb*
.rename $_, s/_HBO_DPM_/_dpm_/r
: Perl Magic.$_
jest specjalną zmienną, która przechowuje każdy element, nad którym iterujemy (wforeach
). Więc tutaj będzie każdy znaleziony plik.s/_HBO_DPM_/_dpm_/
zastępuje pierwsze wystąpienie_HBO_DPM_
z_dpm_
. Działa$_
domyślnie, więc będzie działać na każdej nazwie pliku. Te/r
środki „zastosować tę wymianę na kopię napisu docelowej (nazwa pliku) i powrócić zmodyfikowany łańcuch.rename
Robi to, czego można się spodziewać: to zmienia nazwy plików Więc cała sprawa będzie przemianować nazwę bieżącego pliku (.$_
), Aby sobie z_HBO_DPM_
zastąpiony przez_dpm_
.Możesz napisać to samo, co rozwinięty (i bardziej czytelny skrypt):
źródło
W zależności od rodzaju planowanej zmiany nazwy, użycie vidir z edycją wielu linii może być satysfakcjonujące.
W konkretnym przypadku możesz zaznaczyć wszystkie wiersze w edytorze tekstu i usunąć część nazw plików „ HBO” w kilku naciśnięciach klawiszy.
źródło
vidir
?