Zbiorowe zmiany nazw plików

25

Mam kilka plików:

10.3.100.179_01_20161018_230014_5335.jpg
10.3.100.179_01_20161018_231514_0814.jpg
10.3.100.179_01_20161018_233014_5706.jpg
10.3.100.179_01_20161018_234514_0896.jpg
10.3.100.179_01_20161018_230114_5395.jpg
10.3.100.179_01_20161018_231614_1145.jpg
10.3.100.179_01_20161018_233114_6047.jpg
10.3.100.179_01_20161018_234614_0547.jpg
10.3.100.179_01_20161018_230114_5492.jpg
10.3.100.179_01_20161018_231614_1264.jpg
10.3.100.179_01_20161018_233114_6146.jpg
10.3.100.179_01_20161018_234614_0658.jpg
10.3.100.179_01_20161018_230214_5630.jpg
10.3.100.179_01_20161018_231714_7135.jpg

Chcę zmienić nazwę w tym formacie:

10.4.100.135_01_20161013131108389_TIMING.jpg
10.4.100.135_01_20161013131111390_TIMING.jpg
10.4.100.135_01_20161013131114401_TIMING.jpg
10.4.100.135_01_20161013131117431_TIMING.jpg
10.4.100.135_01_20161013131120418_TIMING.jpg
10.4.100.135_01_20161013131123461_TIMING.jpg
10.4.100.135_01_20161013131126511_TIMING.jpg

Musi usunąć _znacznik czasu i dodać _TIMING.

Jojo Mendoza
źródło
5
Proszę używać spójnych przykładów w swoich pytaniach. Wygląda na to, że chcesz zamienić 10.3.100.179z 10.4.100.135. Czy tego właśnie chcesz, czy chcesz po prostu usunąć _TIMINGi _od czasu?
terdon
3
Dobry czas, aby przypomnieć ludziom, że istnieje standard iso8601 dla dat (który działa zarówno dla nazw plików ORAZ dla wpisów do dziennika) ^^ Więc może powinieneś ponownie rozważyć zmianę nazwy na: RRRR-MM-DDThh: mm: ss.mmm (ex : twój pierwszy plik stałby się: 10.4.100.135_01_2016-10-13T13:11:08.389_TIMING.jpg(a „TIMING” mógłby nawet zostać usunięty, ponieważ teraz wygląda wyraźnie jak data i godzina (i milisekundy), szczególnie gdy standard staje się bardziej rozpowszechniony. T jest częścią standardu, a ja dorastał, aby to lubić (i wyjęcie go łamie standard ^^)
Olivier Dulac
@OlivierDulac Nie polecam używania :w nazwie pliku. Wierzę, że Windows go nie obsługuje.
Justin,
@ Justin dobry punkt. standard zaleca upuszczenie go dla nazw plików. Dałem wersję w pliku
Olivier Dulac

Odpowiedzi:

38

Zainstaluj renameutilsi używaj qmvz ulubionym edytorem tekstu.

qmvładuje wszystkie nazwy do edytora, a po zapisaniu i zamknięciu stosuje zmiany do rzeczywistych plików. Jeśli zmiany są niespójne (np. Dwa pliki mają tę samą nazwę), zostanie przerwane bez dotykania czegokolwiek. Obsługuje również poprawnie okrągłe zmiany nazw.

Zwyklę robię:

$ qmv -f do

tak, że pokazuje tylko jedną kolumnę nazw (do: only-destination-only). Oto jak to wygląda:

qmw

Jeśli połączysz go z wieloma kursorami SublimeText, Atom lub Visual Studio Code, będzie to bardzo ładne i potężne narzędzie do masowej zmiany nazw. Na przykład zrobiłbyś to dla Atom EDITOR="atom -w" qmv -f do.

ateijelo
źródło
1
Witamy w askUbuntu! To jest takie fajne!
αғsнιη
Podpisano to tylko do +! to. ;)
J. Allan
2
Wow, fajne narzędzie i ładna animacja GIF. Świetna pierwsza odpowiedź, zapraszamy! :)
Byte Commander
1
Dzięki @KasiyA za wstawienie obrazu i wszystkim innym za pozytywne komentarze.
ateijelo
1
@kasperd Tak, ostrzeże, że plan zmiany nazwy zawiera błędy i otworzy interaktywną konsolę, w której można podjąć dalsze działania.
ateijelo
27

Użyj rename...

rename -n 's/^([0-9]+\.[0-9]\.[0-9]+\.[0-9]+_[0-9]+_)([0-9]+)_([0-9]+)_([0-9]+)\.jpg/$1$2$3$4_TIMING\.jpg/' *

Dzięki -ntemu wygeneruje to, co zrobi bez wprowadzania żadnych zmian:

rename(10.3.100.179_01_20161018_230014_5335.jpg, 10.3.100.179_01_201610182300145335_TIMING.jpg)
rename(10.3.100.179_01_20161018_231514_0814.jpg, 10.3.100.179_01_201610182315140814_TIMING.jpg)
rename(10.3.100.179_01_20161018_233014_5706.jpg, 10.3.100.179_01_201610182330145706_TIMING.jpg)
rename(10.3.100.179_01_20161018_234514_0896.jpg, 10.3.100.179_01_201610182345140896_TIMING.jpg)

Jeśli wszystko wygląda poprawnie, usuń -n

$ rename 's/^([0-9]+\.[0-9]\.[0-9]+\.[0-9]+_[0-9]+_)([0-9]+)_([0-9]+)_([0-9]+)\.jpg/$1$2$3$4_TIMING\.jpg/' *
$ ls
10.3.100.179_01_201610182300145335_TIMING.jpg  10.3.100.179_01_201610182330145706_TIMING.jpg
10.3.100.179_01_201610182315140814_TIMING.jpg  10.3.100.179_01_201610182345140896_TIMING.jpg

Wyjaśnienie ...

  • s/something/something_else/ wyszukaj i zamień
  • ^ początek nazwy (zakotwiczenie)
  • [0-9] Jakikolwiek numer
  • + jeden lub więcej poprzedzających znaków
  • \.dosłowny .(bez \tego pasuje dowolny znak)
  • () zachować tę część
  • $1$2$3$3 wstecz odniesienia do rzeczy pasujących wcześniej i zachowanych ()

Uwaga: *na końcu polecenia pasuje wszystkie widoczne pliki w bieżącym katalogu. W razie potrzeby użyj bardziej odpowiedniego globu.

Zanna
źródło
2
W niektórych dystrybucjach to polecenie jest dostępne jako prename(p dla perla, ponieważ pierwszy argument jest wyrażeniem perla)
Peter Cordes
12

mmv można to zrobić w następujący sposób:

mmv '*_*_*_*_*.jpg' '#1_#2_#3#4#5_TIMING.jpg'

10.3.100.179_01_20161018_230014_5335.jpg 10.3.100.179_01_201610182300145335_TIMING.jpg

# 1, # 2, # 3, ... odnosi się tutaj do pasującego „*” tutaj.

Jest jeszcze krótszy z:

mmv '*_*_*.jpg' '#1#2#3_TIMING.jpg'
αғsнιη
źródło
9

Inne renamepodejście:

$ rename -n 's/(.*)_(.*)_(.*)\./$1$2$3_TIMING./' *
10.3.100.179_01_20161018_230014_5335.jpg -> 10.3.100.179_01_201610182300145335_TIMING.jpg
10.3.100.179_01_20161018_230114_5395.jpg -> 10.3.100.179_01_201610182301145395_TIMING.jpg
10.3.100.179_01_20161018_230114_5492.jpg -> 10.3.100.179_01_201610182301145492_TIMING.jpg
10.3.100.179_01_20161018_230214_5630.jpg -> 10.3.100.179_01_201610182302145630_TIMING.jpg
10.3.100.179_01_20161018_231514_0814.jpg -> 10.3.100.179_01_201610182315140814_TIMING.jpg
10.3.100.179_01_20161018_231614_1145.jpg -> 10.3.100.179_01_201610182316141145_TIMING.jpg
10.3.100.179_01_20161018_231614_1264.jpg -> 10.3.100.179_01_201610182316141264_TIMING.jpg
10.3.100.179_01_20161018_231714_7135.jpg -> 10.3.100.179_01_201610182317147135_TIMING.jpg
10.3.100.179_01_20161018_233014_5706.jpg -> 10.3.100.179_01_201610182330145706_TIMING.jpg
10.3.100.179_01_20161018_233114_6047.jpg -> 10.3.100.179_01_201610182331146047_TIMING.jpg
10.3.100.179_01_20161018_233114_6146.jpg -> 10.3.100.179_01_201610182331146146_TIMING.jpg
10.3.100.179_01_20161018_234514_0896.jpg -> 10.3.100.179_01_201610182345140896_TIMING.jpg
10.3.100.179_01_20161018_234614_0547.jpg -> 10.3.100.179_01_201610182346140547_TIMING.jpg
10.3.100.179_01_20161018_234614_0658.jpg -> 10.3.100.179_01_201610182346140658_TIMING.jpg

Jeśli wydaje się, że działa tak, jak chcesz, usuń -n.

terdon
źródło
5

Możesz także użyć następujących. Najpierw wykonaj kopię zapasową plików i wypróbuj to:

find . -name "*.jpg" -type f -print0| while read -d $'\0' file
do
    #extension="${file##*.}"
    newfilename=$(echo "${file%.*}" | sed 's/\(.*\)_\(.*\)_/\1\2/')
    mv "$file" "$newfilename""_TIMING.jpg"
done

sed 's/\(.*\)_\(.*\)_/\1\2/')usuwa _znaki ze znacznika czasu.

Na przykład:

user@host$ ls -lart
total 8
drwxrwxr-x 6 user user 4096 Oct 21 10:21 ..
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230014_5335.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231514_0814.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233014_5706.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234514_0896.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230114_5395.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231614_1145.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233114_6047.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234614_0547.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230114_5492.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231614_1264.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233114_6146.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234614_0658.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230214_5630.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231714_7135.jpg
drwxrwxr-x 2 user user 4096 Oct 21 10:30 .

user@host$ find . -name "*.jpg" -type f -print0 | while read -d $'\0' file
> do
>  newfilename=$(echo "${file%.*}" | sed 's/\(.*\)_\(.*\)_/\1\2/')
>  mv $file $newfilename"_TIMING.jpg"
> done

10:35:20 t $ ls -lart
total 8
drwxrwxr-x 6 user user 4096 Oct 21 10:21 ..
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182300145335_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182315140814_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182330145706_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182345140896_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182301145395_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182316141145_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182331146047_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182346140547_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182301145492_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182316141264_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182331146146_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182346140658_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182302145630_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182317147135_TIMING.jpg
drwxrwxr-x 2 user user 4096 Oct 21 10:35 .
Mustafa DOGRU
źródło
1
to najlepsze rozwiązanie. Oczywiście soulanna Zanna jest idealna dla kilku plików, ale ponieważ globbing jest wykonywany przez powłokę, ich rozwiązanie może zawieść w przypadku dużej liczby plików (zbyt długi ciąg poleceń).
rexkogitans
@rexkogitans: Jeśli korzystasz z nowoczesnego systemu Linux (tj. dowolnej wersji Ubuntu), limit długości wiersza poleceń wynosi wiele megabajtów. A jeśli jest to problem, możesz użyć, find -maxdepth 1 -exec rename ... {} +aby wsadować listę bieżącego katalogu do wiersza polecenia zmiany nazwy. (dodaj -name *.jpglub cokolwiek chcesz). To zadziała znacznie szybciej niż pętla powłoki, która rozwidla + exec sedi mvdla każdej nazwy pliku, zamiast tylko zmiany nazwy wywołania systemowego. (Można się pozbyć sedkorzystania z wbudowanych wyrażeń regularnych basha, ale rozwidlanie mvjest nadal powolne.)
Peter Cordes
2

Prawdopodobnie skończyłeś, ale oto (proste) całe bashrozwiązanie:
Czy „proste ... rozwiązanie bash” jest oksymoronem?

#!/bin/bash

#loop through all files ending in .jpg
for f in *.jpg;
do

    #cut out everything to the timestamp
    firsthalf=${f%_*_*_*}

    #get from the timestamp on
    lasthalf=${f#*_*_}

    #remove (all) underscores from timestamp
    #note the 2 forward slashes...
    lasthalf=${lasthalf//_/}

    #get our extension
    ext=${lasthalf##*.}

    #now we can remove the extension
    lasthalf=${lasthalf%.*}

    #rename the file
    #change `mv` to `echo` if you want to do a trial run first...
    mv "$f" "${firsthalf}_${lasthalf}_TIMING.${ext}"

done;

PS: Logika w pętli została przetestowana z jedną z twoich przykładowych nazw plików. Przeszło.

J. Allan
źródło
1
Prawdopodobnie lepiej użyć wyrażenia regularnego z [[ $f ~= (.*)_(.*)_(.*)_(.*)\.jpg ]]; newname=${BASH_REMATCH[1]${BASH_REMATCH:2:4}TIMING.jpgczymś innym . (całkowicie niesprawdzone i prawdopodobnie błędne, ale ogólną ideą jest to, że grupy przechwytywania przechodzą do tablicy BASH_REMATCH.)
Peter Cordes
@PeterCordes: To dobra uwaga! Nigdy nie używałem ( bash) przechwytywania grup, i szczerze mówiąc, bash nie jest pierwszym językiem, w którym chciałbym je wypróbować. (Myślę, że bashto brzydki język.) Mimo to jest to dobre rozwiązanie i nauczyło mnie czegoś tak godnego podziwu.
J. Allan,
Tak, głównym powodem przetwarzania tak dużej ilości tekstu w czystym bashu jest pisanie funkcji uzupełniania tabulatorów, które powinny być szybkie. Nadaje zupełnie nowe znaczenie zwrotowi „brzydki kod” ...
Peter Cordes
@PeterCordes: Rozumiem, o co mi chodzi , choć nie sądzę, że kod jest „brzydki”. Być może nie jest to 2-liniowe rozwiązanie, które podałeś, ale o ile mnie to nie jest trudne; plus jest dobrze skomentowany ...
J. Allan,
Mówiłem o tym, że kod zakończenia bashu jest ogólnie brzydki (lub przynajmniej trudny do odczytania). W rzeczywistości nie jest to naprawdę brzydkie, po prostu nieco oszałamiające (np. Przekazywanie argumentów przez ref w bashu przez przekazanie nazwy zmiennej i użycie przez callee printf -v "$3" ...ustawienia zmiennej, której nazwa jest w nazwie $3). Rozebranie całej linii poleceń i odłożenie jej z powrotem razem jest to dość trudne do śledzenia / debugowania, przynajmniej znalazłem to w ten sposób, próbując to naprawić / naprawić błędy. Zobacz kod na github
Peter Cordes
1

Jeśli możesz użyć GUI, polecam pyRenamer .

Jest obecny w większości dystrybucji, fi w Ubuntu:

sudo apt-get install pyrenamer

Może zrobić wszystko, co chcesz i więcej.

  • Może używać wzorów, dodawać lub pomijać tekst.
  • Może uzyskać dostęp do danych EXIF ​​w przypadku zmiany nazw zdjęć, dzięki czemu można generować wzorce na podstawie daty / godziny itp.
  • Może zmieniać metadane podczas zmiany nazw plików muzycznych.
  • Ponadto ma podgląd , który może zapobiec niektórym błędom trudnym do przywrócenia.
jrierab
źródło
Do downvoter ... Chcesz wyjaśnić, dlaczego? OP nie określił, czy GUI jest opcją, czy nie. Widzę, że większość odpowiedzi dotyczy sposobu konsoli / skryptu, ale wielu użytkowników doceni rozwiązanie GUI. A może pyRenamer ma jakąś wadę, o której nie wiem. W każdym razie lubię znać powody głosów negatywnych.
jrierab
Mogę również zasugerować Thunar Bulk Renamer, aby uzyskać interaktywne GUI.
Tony Martin
@TonyMartin To powinien być komentarz pod znakiem zapytania, nie ma to nic wspólnego z odpowiedzią
Sergiy Kolodyazhnyy
0

Oto Twoje surowe wbudowane find +xargs + sed+ mvoneliner (Love Oneliner):

find . -name "*.jpg" -print0 | sort -z | xargs -0 sh -c 'for filename; do mv "$filename" $(echo "${filename}" | sed "s/\([0-9]\{8\}\)_\([0-9]\{6\}\)_\([0-9]\{4\}\)/\1\2\3_TIMING/g"); done' sh

Wyjaśnienie:

  • find . -name "*.jpg" | sort | xargs sh -c <command> sh : wyświetl listę wszystkich plików JPEG w bieżącym katalogu, a następnie wykonaj polecenie powłoki dla każdego z nich (sortowanie jest oczywiście opcjonalne, ale zachowaj porządek, jeśli gdzieś się logujesz)

  • -print0, -z , -0: To dobry zwyczaj, aby odrębne pozycje z binarnym 0gdy tokenizing nazw plików, aby uniknąć problemów z in-the-middle-białe przestrzenie (choć nie twoja sprawa)

  • mv "$filename" $(echo "${filename}" | sed "s/\([0-9]\{8\}\)_\([0-9]\{6\}\)_\([0-9]\{4\}\)/\1\2\3_TIMING/g");: (odwrotne ukośniki w sedwyrażeniu regularnym nie pomagają w jego czytelności, ale jest to proste) zmień nazwę każdego pliku, zastępując sekwencję podkreśloną 8 + 6 + 4 cyfr ich ciągłą konkatenacją plus to _TIMINGcoś (\i jest to odwołanie do i- grupa wyrażeń regularnych).


Refs: Xargs - mężczyzna sed

Campa
źródło