Odejmij 1 od wszystkich nazw plików (zmień ich nazwy) w katalogu.

17

Mam katalog zawierający pliki obrazów o nazwach takich jak

image1.jpg 
image2.jpg 
image3.jpg
...

Niestety, nazwy obrazów muszą być zerowe, więc image1.jpgpowinno być image0.jpg, image2.jpgpowinno być image1.jpgi tak dalej.

Mogę napisać skrypt, aby wygenerować takie polecenia mv, umieścić je w skrypcie powłoki, a następnie wykonać je -

mv image1.jpg image0.jpg
mv image2.jpg image1.jpg
mv image3.jpg image2.jpg
...

Ale przypuszczam, że jest lepszy sposób na uniks. Więc co to jest?

Wes
źródło
6
To właściwie najprostszy sposób na zrobienie tego, o ile nie ma żadnych luk. ( for i in $(seq 0 100); do mv image$[i+1].jpg image$i.jpg; done)
Ricky Beam
5
Czy kolejność zdjęć jest ważna? Jeśli nie, po prostu zmień nazwę ostatniego obrazu od imageN.jpgna image0.jpgi gotowe.
jnovacho
@jnovacho, całkiem sprytny! Ale tak, kolejność obrazów jest ważna.
Wes

Odpowiedzi:

20

Nazwa starego dobrego Perla:

rename 's/(\d+)(\.jpg)/($1-1).$2/e' *

[Uwagi]

Numery zdjęć powinny być większe niż 0.

Jeśli obrazy są większe niż 9 i nie mają zera, użyj, $(ls -v1 *)aby uniknąć zatkania. Zaproponowane przez @arielf i zauważone przez @Graeme.

W razie wątpliwości używaj również -vdo pełnego mówienia i -ndo braku działania.


źródło
Co oznacza „e”?
Wes
3
„e” oznacza ocenę, sekcja zastępowania zostanie oceniona. patrz takżeperlreref
6
Pliki należy przekazywać w kolejności rosnącej, aby uniknąć zablokowania. Działa to dobrze tylko wtedy, gdy jest mniej niż 10 plików (lub jeśli liczby mają zera na początku).
Graeme
Zauważyłem to już, również nie może być 0w źródłach.
2
zamień *na końcu na, `ls -v1 *`a będziesz bezpieczniejszy od zatykania. Przejdzie od najniższej liczby do najwyższej.
arielf
6

Wygenerowane mvpolecenia można przesyłać strumieniowo do bash. Więc nie musisz kopiować ich w skrypcie i wykonywać tego. Widzieć:

command_that_generates_mv_commands | bash

I wszystko zostanie wykonane, co jest przesyłane potokowo bash.

chaos
źródło
To nie jest fajniejsze. :)Rozwiązuje problem, więc +1.
JMCF125
5

Możesz iterować na wyjściu ls, ten działa na twoim przykładzie:

i=0 
for file in $(ls *.jpg | sort) ; do 
     mv $file $(echo $file | sed 's/[0-9]*.jpg$/'${i}'.jpg/')
     i=$((++i))
done

Musisz być na tej samej ścieżce swoich plików

babasbot
źródło
1
Lepszy w użyciu -ilub -nz mv, zapobiegnie nadpisywaniu w przypadkach krawędzi.
Graeme
nie sort -Vbyłoby lepiej zamiast tego?
user80551
sortnie będzie działać, to pokaże image10.jpgprzed image1.jpgco może być problemem. Potrzebujesz sort -nk 1.8jak w odpowiedzi @ Graeme.
terdon
@ user80551, sort -Vto dobry pomysł, doda go do mojej odpowiedzi. Mogą być jednak inne przypadki krawędzi, po prostu dobra rada, aby dodać tego rodzaju opcje z pytaniami takimi jak ten, na wypadek, gdyby ktoś skopiował i wyrządził jakieś szkody.
Graeme
4

Poniższe wydaje się działać dla wszystkiego, co pasuje do wzorca imageNUMBER.jpg. Umieściłem echoprzed mvpoleceniem, aby najpierw pokazać, co zrobi polecenie; aby faktycznie zmienić nazwę, po prostu usuńecho

for i in `ls image*.jpg|sort -V` ; do 
    x=`echo $i|sed -e "s/image\(.*\).jpg/\1/"`
    y=$(( $x - 1 ))
    echo mv -i $i image$y.jpg
done

W pierwszym wierszu ls image*.jpg|sort -Vspowoduje wyświetlenie plików JPG z rosnącymi liczbami w nazwie pliku. x=Linia wyodrębnia numer z pliku. y=Linia następnie zmniejsza liczbę o jeden. Wejściowa nazwa pliku i ynumer są następnie używane w mvpoleceniu, gdzie -iflaga powiadomi Cię przed zastąpieniem pliku.

W przypadku mojego małego testu uzyskano wynik:

mv -i image1.jpg image0.jpg
mv -i image2.jpg image1.jpg
mv -i image123.jpg image122.jpg

Osobiście sugeruję zmianę nazwy na inną nazwę pliku, ponieważ teraz kolejność przetwarzania plików może mieć duże znaczenie.

brm
źródło
1
Lepszy w użyciu -ilub -nz mv, zapobiegnie nadpisywaniu w przypadkach krawędzi.
Graeme
Bardzo dobra sugestia,
zredaguję
W macOS powinieneś użyć sort -n, -Vopcja nie istnieje.
Vincent Sit
4

Korzystanie ze perlskryptu prename, który jest dowiązany symbolicznie do zmiany nazwy w dystrybucjach opartych na Debianie, również wymaga GNU find/ sort. Pliki są ułożone w porządku rosnącym, aby zapobiec nadpisaniu.

find . -regex '\./image[0-9]+\.jpg' -print0 | sort -zV |
  xargs -0 rename -n 's/(\d+)\.jpg$/@{[$1-1]}.jpg/'

Usuń, -ngdy masz pewność, że robi to, co chcesz. Ostrzeże o plikach już istniejących przed zrobieniem tego. Jednak tak długo, jak pokazuje, że nazwy plików są zmieniane w kolejności rosnącej, nie będzie żadnych konfliktów, gdy zostanie uruchomiony w trybie rzeczywistym.

Graeme
źródło
Plik już istnieje z tym problemem.
Wes
4

Z zsh:

autoload zmv # (in ~/.zshrc)
zmv -Qf -n 'image(<->).jpg(n)' 'image$(($1-1)).jpg'

(usuń, -ngdy będzie szczęśliwy).

(n)polega na posortowaniu listy numerycznie, dlatego image9.jpgwcześniej zmienia się jej nazwę image10.jpg.

Stéphane Chazelas
źródło