Как переименовать файлы с упорядочением с помощью Bash {thisfile.jpg -> newfile1.jpg, thatfile.jpg -> newfile2.jpg}

Допустим, у меня есть 100 файлов jpg.

DSC_0001.jpg
DSC_0002.jpg
DSC_0003.jpg
....
DSC_0100.jpg

И я хочу переименовать их как

summer_trip_1.jpg
summer_trip_2.jpg
summer_trip_3.jpg
.....
summer_trip_100.jpg    

Итак, я хочу, чтобы эти свойства были изменены: 1. имя файла 2. порядок файла (поскольку файлы были созданы в порядке по дате)

Как я могу добиться этого с помощью bash? Нравиться:

for file in *.jpg ; do mv blah blah blah ; done

Благодарю вас!


person YOUNG    schedule 04.12.2013    source источник


Ответы (4)


Это очень просто: создайте переменную и увеличивайте ее на каждом шаге.

Пример:

cur_number=1
prefix="summer_trip_"
suffix=""
for file in *.jpg ; do
    echo mv "$file" "${prefix}${cur_number}${suffix}.jpg" ;
    let cur_number=$cur_number+1  # or :  cur_number=$(( $cur_number + 1 ))
done

и как только вы решите, что все готово, уберите echo, чтобы произошло mv.

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

сдача

for file in *.jpg ; do

в

for file in $( ls -1t *.jpg ) ; do

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

Наконец, вместо ${cur_number} вы можете использовать $(printf '%04s' "${cur_number}"), чтобы новое число имело ведущие нули, что значительно упростило сортировку.

person Olivier Dulac    schedule 04.12.2013
comment
Спасибо за ваш вклад, Оливье. Я проверю позже сегодня вечером или завтра и обновлю оценку :) - person YOUNG; 05.12.2013
comment
Я попробовал ваше предложение, но ничего не изменилось. Он повторил мои команды, но имена файлов остались прежними. и если я командую cur_number=$(($cur_number + 1)), вместо cur_number=$cur_number+1, переменная не изменяется и фиксирует окончательное число переменной (т.е. если 5 циклов, то переменная исправлено на 5.) - person YOUNG; 06.12.2013
comment
Моя машина работает под управлением Mac OS X 10.6.9. Может ли это быть причиной этой беды? - person YOUNG; 06.12.2013
comment
Боже мой. Я просто опозорился. Я забыл убрать эхо. Почему вы поместили это в сценарий в первую очередь? Я новичок в мире CS, и мне интересно, является ли это какой-то условностью при написании сценария? - person YOUNG; 06.12.2013
comment
Я сделал ваши команды в виде сценария, и теперь это одна из моих команд DIY в Mac OS. Я мог бы редактировать префиксы и суффиксы в сценарии каждый раз, когда я хочу переименовать файлы с новыми именами файлов, но было бы здорово, если бы я мог задавать префиксы и суффиксы в качестве аргументов при запуске команды. Есть предложения, Оливье? - person YOUNG; 06.12.2013
comment
например, имя сценария оболочки — rename_jpg. Поэтому я хотел бы иметь возможность командовать в Терминале, например: User$ rename_jpg prefix suffix - person YOUNG; 06.12.2013
comment
@YOUNG:: это просто. В вашем сценарии $1 и $2 будут первым и вторым параметрами. Просто есть prefix="$1" ; suffix="$2" . И если вы хотите также указать значения по умолчанию (в случае, если вы не предоставляете 2 параметра, а только первый или 0): prefix="${1:-default_value}" ; suffix="${2:-default_value_2}" позволит это. - person Olivier Dulac; 08.12.2013
comment
@YOUNG: что касается эха, обычно рекомендуется сначала протестировать скрипт, убедиться, что он правильно выполняет команду, и исправить его, пока он не сделает это. ТОГДА вы вынимаете эхо, чтобы фактически выполнить команду (особенно полезно для команд, которые меняют вещи, таких как mv rm и т. д.) - person Olivier Dulac; 08.12.2013
comment
Оливье, я искренне благодарю вас за ваши прекрасные советы. Он делает свою работу, и это то, что я давно хотел реализовать! Похоже, вы специалист в этой области. Не могли бы вы порекомендовать мне несколько хороших библиотек или руководств по написанию сценариев оболочки, пожалуйста? Я думаю, что собираюсь прочитать один из документации разработчика Apple. В любом случае большое спасибо из Хельсинки! :D - person YOUNG; 13.12.2013
comment
@YOUNG: лол, спасибо за добрые слова, но я не такой эксперт в этой области, как, например, Стефан Шазелас (см. его ответы!). Я стараюсь сосредоточиться на удобочитаемости (а не на краткости) и переносимости (а не на аккуратности). Я дам вам несколько советов по написанию сценариев. Но для всего, что связано с bash/shell, я настоятельно рекомендую вам прочитать (возможно, после небольшого написания сценария) отличный материал на mywiki.wooledge.org/BashFAQ , mywiki.wooledge.org/BashPitfalls — 2 превосходных читает (опять же, возможно, после того, как вы уже знаете скрипты...) - person Olivier Dulac; 13.12.2013
comment
@YOUNG: хорошая отправная точка: linuxcommand.org/index.php . Вторая часть (linuxcommand.org/lc3_writing_shell_scripts.php) посвящена сценариям (но первая часть, linuxcommand.org/lc3_learning_the_shell.php, о повседневном использовании оболочки, по-видимому, тоже неплохо) . Я не знаю, предоставляют ли они только переносные (sh-совместимые) советы, поэтому, возможно, будьте осторожны, чтобы вы могли узнать вещи, которые работают только в Linux или последних системах с программами GNU [многие компании все еще используют более старые среды где у вас есть только древние команды, и вас легко могут укусить!] - person Olivier Dulac; 13.12.2013
comment
Обычно GNU-эквивалент unix-программ (например, GNU ls, tar, cc, grep, find и т. д.) добавляет много приятных вещей [и опций] + также исправляет некоторые неприятные неприятности. Например, примитивный tar не удаляет начальный «/» из абсолютных имен файлов. Таким образом, при извлечении он идет туда, где был исходный файл [например: /etc/hosts], а не в подкаталоге, в который вы хотите его перейти... [например: /my/subdir/etc/hosts]. Вы учитесь уставать от этого при использовании старой производственной системы! Поэтому я всегда стараюсь быть осторожным и стараюсь указывать на эти вещи в своих [и других] ответах. Портативность превыше всего, имхо. - person Olivier Dulac; 13.12.2013
comment
Привет, Оливье! Мне очень жаль за поздний ответ. Я был на зимних каникулах из школы, а также из-за компьютера. Большое спасибо за ваши супер добрые советы. linuxcommand.org кажется довольно удобным для начинающих! Может быть, я начну с этого :) Я ценю вашу доброту и счастливого нового года!!! - person YOUNG; 29.12.2013
comment
@YOUNG: Рад, что это помогло :) С Новым годом! - person Olivier Dulac; 30.12.2013

Как насчет использования rename ?

 rename DSC_ summer_trip_ *.jpg

См. справочную страницу rename.

person dpp    schedule 04.12.2013
comment
@ user2719058 - Не могли бы вы уточнить? Если вы говорите об использовании, обратите внимание, что существует два варианта переименования: один Perl-скрипт, изначально написанный Ларри Уоллом, и бинарная версия, предварительно установленная в Linux. То, что у меня есть, это позже. Посмотрите на справочную страницу для использования, если вам все еще не ясно. - person dpp; 05.12.2013
comment
Спасибо за ваш вклад, dpp. Я проверю позже сегодня вечером или завтра и обновлю оценку :) - person YOUNG; 05.12.2013
comment
@dpp Ах, ты прав. В моих системах Debian двоичный файл rename устанавливается как rename.ul, поэтому я забыл об этом. Я вернул свой отрицательный голос. Однако вы можете рассмотреть возможность добавления этого уточнения к своему ответу. - person user2719058; 05.12.2013

Это работает, если ваши исходные числа заполнены нулями до одинаковой длины:

i=0; for f in DSC_*.jpg; do mv "$f" "summer_trip_$((++i)).jpg"; done 
person user2719058    schedule 04.12.2013
comment
Спасибо за ваш вклад, пользователь 2719058. Я проверю позже сегодня вечером или завтра и обновлю оценку :) - person YOUNG; 05.12.2013
comment
Спасибо, но не все мои файлы имеют системные имена :( - person YOUNG; 06.12.2013

Если я правильно понимаю вашу цель:

Итак, я хочу, чтобы эти свойства были изменены: 1. имя файла 2. порядок файла (поскольку файлы были созданы в порядке по дате)

если количество переименованных файлов должно увеличиваться по дате создания файла, используйте следующий цикл for:

for file in $(ls -t -r *.jpg); do

-t сортирует по mtime (время последней модификации, а не точное время создания, сначала самые новые), а -r меняет порядок, в котором самые старые сначала. На тот случай, если исходные номера файлов .jpg не в том порядке, в котором были сделаны снимки. Как упоминалось ранее, это не сработает, если имена файлов содержат пробелы. Если в ваших файлах есть пробелы, попробуйте изменить переменную IFS перед циклом for:

IFS=$'\n'

Это приведет к разделению результатов команды 'ls' только на новые строки (не пробелы). Также это не удастся, если в имени файла есть новая строка (довольно экзотическое ИМХО :). Изменение IFS может иметь некоторые тонкие последствия в вашем скрипте, поэтому вы можете сохранить старый и восстановить после цикла.

person Mindaugas Kubilius    schedule 05.12.2013
comment
Ваша командная строка не работает с файлами, имена которых содержат пробелы. Посмотрите пост Оливье. - person YOUNG; 06.12.2013
comment
Неплохо подмечено. Я знал о комментарии Оливье, но если в ваших файлах есть пробелы, то да, это не сработает. Немного отредактировал ответ. Настройка IFS должна помочь. Просто у меня нет Mac OSX для тестирования, и я предполагаю, что bash на Mac использует \n для разделителя новой строки (не \r). - person Mindaugas Kubilius; 06.12.2013