Массовое переименование файлов

25

У меня есть несколько файлов:

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

Я хочу переименовать с этим форматом:

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

Необходимо удалить _метку времени и добавить _TIMING.

Jojo Mendoza
источник
5
Пожалуйста, используйте последовательные примеры в своих вопросах. Похоже, вы хотите заменить 10.3.100.179на 10.4.100.135. Это то, что вы хотите, или вы просто хотите убрать время _TIMINGи _время?
тердон
3
Самое время напомнить людям, что существует стандарт iso8601 для дат (который работает как для имен файлов, так и для записей журнала) ^^ Так что, возможно, вам следует пересмотреть переименование, чтобы оно стало: YYYY-MM-DDThh: mm: ss.mmm (ex : ваш первый файл стал бы: 10.4.100.135_01_2016-10-13T13:11:08.389_TIMING.jpg(и тогда «TIMING» можно было бы даже удалить, так как теперь он выглядит четко как дата и час (и миллисекунды), особенно когда стандарт становится более распространенным. T является частью стандарта, а я вырос, чтобы полюбить это (и выход из него нарушает стандарт ^^)
Оливье Дюлак
@OlivierDulac Я бы не рекомендовал использовать :в имени файла. Я считаю, что Windows не поддерживает это.
Джастин
@ Джастин, хорошо. стандарт рекомендует отбрасывать его для имен файлов. Я дал версию в файле
Оливье Дюлак

Ответы:

38

Установите renameutilsи используйте qmvс вашим любимым текстовым редактором.

qmvзагружает все имена в ваш редактор, а когда вы сохраняете и закрываете его, он применяет ваши изменения к реальным файлам. Если изменения противоречивы (например, два файла имеют одно и то же имя), они будут прерваны, ничего не трогая. Он также правильно обрабатывает циклические переименования.

Я обычно делаю:

$ qmv -f do

так что он показывает только один столбец имен (do: destination-only). Вот как это выглядит:

qmw

Если вы объедините его с несколькими курсорами SublimeText, Atom или Visual Studio Code, это станет очень хорошим и мощным инструментом для массового переименования. Например, для Atom, вы бы сделали EDITOR="atom -w" qmv -f do.

ateijelo
источник
1
Добро пожаловать в AskUbuntu! Это так круто!
α'sнιη
Подписал его только на +! Это. ;)
Дж. Аллан
2
Ничего себе, хороший инструмент и хорошая анимация GIF. Отличный первый ответ, добро пожаловать! :)
Byte Commander
1
Спасибо @KasiyA за вставку изображения и спасибо всем за положительные комментарии.
ateijelo
1
@kasperd Да, он предупредит, что план переименования содержит ошибки, и откроет интерактивную консоль, где можно предпринять дальнейшие действия.
ateijelo
27

Используйте 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/' *

При -nэтом будет выводиться то, что он собирается делать без каких-либо изменений:

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)

Если это выглядит правильно, удалите -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

Объясняя ...

  • s/something/something_else/ поиск и замена
  • ^ начало названия (якорь)
  • [0-9] любой номер
  • + один или несколько из предшествующего символа
  • \.литерал .(без \этого соответствует любому символу)
  • () чтобы сохранить эту часть
  • $1$2$3$3 обратные ссылки на вещи, сопоставленные ранее и сохраненные с ()

Примечание: *в конце команды отображаются все видимые файлы в текущем каталоге. При необходимости используйте более подходящий шарик.

Занна
источник
2
На некоторых дистрибутивах эта команда доступна как prename(p для perl, потому что первый аргумент является выражением perl)
Питер Кордес
12

mmv можно сделать как в следующем:

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, ... ссылаются здесь на соответствующие '*' здесь.

Это еще короче с:

mmv '*_*_*.jpg' '#1#2#3_TIMING.jpg'
αғsнιη
источник
9

Другой renameподход:

$ 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

Если это работает так, как вы хотите, удалите -n.

terdon
источник
5

Вы также можете использовать следующее. Сначала сделайте резервную копию ваших файлов и попробуйте это:

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/')удаляет _символы в метке времени.

Например:

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 .
Мустафа ДОГРУ
источник
1
это лучшее решение. Конечно, душа Zanna идеально подходит для пары файлов, но поскольку глобализация выполняется оболочкой, их решение может потерпеть неудачу на большом количестве файлов (слишком длинная командная строка).
rexkogitans
@rexkogitans: если вы работаете в современной системе Linux (то есть в любой версии Ubuntu), ограничение длины командной строки составляет несколько мегабайт. И если это проблема, вы можете использовать find -maxdepth 1 -exec rename ... {} +пакетную распечатку текущего каталога в командной строке переименования. (добавить -name *.jpgили все, что вы хотите). Это будет выполняться намного быстрее, чем цикл оболочки, который разветвляется + execs sedи mvдля каждого имени файла, вместо просто системного вызова переименования. (Вы можете избавиться от sedиспользования встроенных в bash регулярных выражений, но разветвление mvвсе еще медленное.)
Питер Кордес
2

Вы, вероятно, закончили, но вот (простое) bashрешение для всех :
"Простое ... решение для bash" - оксюморон?

#!/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: логика в цикле была проверена с одним из ваших примеров имен файлов. Это прошло.

Дж. Аллан
источник
1
Вероятно, лучше использовать регулярное выражение Bash с [[ $f ~= (.*)_(.*)_(.*)_(.*)\.jpg ]]; newname=${BASH_REMATCH[1]${BASH_REMATCH:2:4}TIMING.jpgили что-то. (полностью непроверено и, вероятно, неправильно, но общая идея состоит в том, что группы захвата входят в массив BASH_REMATCH.)
Питер Кордес,
@PeterCordes: Это хороший момент! Я никогда не использовал ( bash) захват групп, и, если честно, bash - не первый язык, на котором я их пробую. (Я думаю, что bashэто некрасивый язык.) Тем не менее, это хорошее решение, и оно научило меня чему-то так.
Дж. Аллан
Да, главная причина, по которой такая большая обработка текста в чистом bash, заключается в написании быстрых функций завершения табуляции. Это придает совершенно новый смысл фразе «уродливый код» ...
Питер Кордес
@PeterCordes: Я понимаю вашу точку зрения, хотя я не думаю, что этот код "уродлив". Это может быть не решение с двумя строками, которое вы дали, но это не сложно прочитать, насколько я понимаю; плюс это хорошо прокомментировано ...
Дж. Аллан
Я говорил о том, что код завершения bash вообще ужасен (или, по крайней мере, труден для чтения). Это на самом деле не очень уродливо, просто несколько сногсшибательно (например, передача аргументов с помощью ref в bash выполняется путем передачи имени переменной и использования вызываемого объекта printf -v "$3" ...для установки переменной, в которой находится имя $3.) Разобрать всю командную строку и вернуть ее обратно вместе довольно сложно следить / отлаживать, по крайней мере, я нашел это таким образом, пытаясь очистить / исправить ошибки. Смотрите код на github
Питер Кордес
1

Если бы вы могли использовать графический интерфейс, я бы порекомендовал pyRenamer .

Он присутствует в большинстве дистрибутивов, например, в Ubuntu:

sudo apt-get install pyrenamer

Он может делать все, что вы хотите и даже больше.

  • Он может использовать шаблоны, добавлять или подавлять текст.
  • Он может получить доступ к данным EXIF ​​при переименовании фотографий, поэтому вы можете создавать шаблоны на основе даты / времени и т. Д.
  • Может использовать некоторые метаданные при переименовании музыкальных файлов.
  • Кроме того, он имеет предварительный просмотр , который может предотвратить некоторые ошибки, которые трудно исправить.
jrierab
источник
Для downvoter ... Не хочешь объяснить, почему? OP не указал, был ли GUI опцией или нет. Я вижу, что большинство ответов идет в направлении консоли / сценария, но многие пользователи оценят решение с графическим интерфейсом. Или, может быть, у pyRenamer есть какой-то недостаток, о котором я не знаю. В любом случае, мне нравится знать причины для отрицательных голосов.
jrierab
Могу ли я также предложить Thunar Bulk Renamer для быстрого интерактивного подхода с графическим интерфейсом.
Тони Мартин
@TonyMartin Это должен быть комментарий под вопросом, это никак не связано с ответом
Сергей Колодяжный
0

Вот ваш сырой встроенный find + xargs+ sed+ mvOneliner (любовь oneliners):

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

Объяснение:

  • find . -name "*.jpg" | sort | xargs sh -c <command> sh : вывести список всех JPEG-файлов в текущем каталоге, а затем выполнить команду оболочки для каждого из них (сортировка, конечно, не обязательна, но если вы куда-то входите, то немного чище)

  • -print0, -z, -0: Это хорошая привычка к отдельным пунктам с двоичным 0когда tokenizing имен файлов , чтобы избежать проблем с в-середины белого-пространство (не ваш случай , хотя)

  • mv "$filename" $(echo "${filename}" | sed "s/\([0-9]\{8\}\)_\([0-9]\{6\}\)_\([0-9]\{4\}\)/\1\2\3_TIMING/g");: (Слеш sed«s регулярного выражение не поможет читаемости, но это просто) переименовать каждый файл, заменив подчеркивание-separeted последовательности 8 + 6 + 4 цифр с их непрерывной конкатенацией плюс этой _TIMINGвещью ( \iв обратную ссылки на i- группа регулярных выражений).


Refs: Xargs - человек сед

Campa
источник