Включить имя папки при переименовании файла в Linux

Я уже использовал эту команду, чтобы переименовать файлы в нескольких каталогах и изменить JPG на jpg, поэтому у меня есть согласованность.

find . -name '*.jpg' -exec sh -c 'mv "$0" "${0%.JPG}$.jpg"' {} \;

У вас есть идеи, как изменить это, чтобы включить имя папки в имя файла?

Я выполняю это в папке, содержащей около 2000 папок (SKU) или продуктов ... и внутри каждой папки SKU есть 9 изображений. 1.jpg 2.jpg .... 9.jpg.

Итак, в итоге у меня есть 2000 изображений с именами 1.jpg, 2.jpg... 9.jpg. Мне нужно, чтобы эти файлы были уникальными, например:

folder-name-1.jpg ... folder-name.2.jpg ... и так далее, в каждой папке.

Любая помощь будет оценена.


person pzd060    schedule 07.02.2014    source источник
comment
Переименование 1.jpg в folder-name-1.jpg не делает его уникальным. По сути, вы пытаетесь добавить префикс ко всем именам файлов.   -  person devnull    schedule 07.02.2014
comment
Если бы вы сами создали команду, это было бы легко. Перестаньте использовать фрагменты из сети. это опасно   -  person hek2mgl    schedule 07.02.2014
comment
rename из дистрибутива Perl может помочь.   -  person devnull    schedule 07.02.2014
comment
devnull — имя папки на самом деле является SKU продукта, поэтому оно будет уникальным. hek2mgl — я php-разработчик, линукс — не моя сила, и я тестировал скрипт локально, прежде чем делать это на сервере.   -  person pzd060    schedule 07.02.2014
comment
@ pzd060 Именно это я и сказал: префикс имен файлов с заданной строкой не сделает их уникальными.   -  person devnull    schedule 07.02.2014
comment
@devnull Да, но эта строка должна быть известна (я не могу использовать случайную строку), потому что тогда мне придется использовать ее для импорта этих изображений в Magento через Excel. Поэтому я должен иметь возможность сопоставлять файлы ... с Excel.   -  person pzd060    schedule 07.02.2014


Ответы (3)


Например, я могу сделать следующее:

$ find . -iname '*.jpg' | while read fn; do name=$(basename "$fn") ; dir=$(dirname "$fn") ; mv "$fn" "$dir/$(basename "$dir")-$name" ;done
./lib/bukovina/version.jpg ./lib/bukovina/bukovina-version.jpg
./lib/bukovina.jpg ./lib/lib-bukovina.jpg
person Малъ Скрылевъ    schedule 07.02.2014
comment
Для проверки я попробовал find ../D44203 -iname '2.jpg' | while read fn; do name=$(basename "$fn") ; dir=$(dirname "$fn") ; mv "$fn" "$dir/$(basename $(pwd))-$name" ;done и получил ВСЕ?A1?PICS?D44203-2.jpg ... что неверно, должно быть D44203-2.jpg - person pzd060; 07.02.2014
comment
@ pzd060 ALL?A1?PICS?D44203-2.jpg ... which is not correct, it should be D44203-2.jpg должно быть что? Я не понял. Вам не нужна папка перед файлом? - person Малъ Скрылевъ; 07.02.2014
comment
Я хотел проверить с помощью ../D44203 ... поэтому перед запуском `find затрагивается только 1 файл. -iname'*.jpg' `потому что это переименует 20 000 файлов, и я хочу быть уверен, что это работает. - person pzd060; 07.02.2014
comment
@pzd060 замените mv на echo и покажите часть результата. - person Малъ Скрылевъ; 07.02.2014

Вы можете использовать тонкий однострочный:

find . -name '*.jpg' -execdir \
      bash -c 'd="${PWD##*/}"; [[ "$1" != "$d-"* ]] && mv "$1" "./$d-$1"' - '{}' \;

Эта команда использует безопасный подход для проверки того, не предшествует ли имя образа текущему имени каталога. Вы также можете запускать его несколько раз, и имя изображения не будет переименовано после первого запуска.

person anubhava    schedule 07.02.2014
comment
На моем локальном компьютере это работало отлично ... но когда я пытаюсь это сделать на сервере, я получаю сообщение: невозможно переместить ./8.jpg' to ./D46107-./8.jpg': No such file or directory, у вас есть идеи, почему? - person pzd060; 07.02.2014
comment
Вы уверены, что использовали -execdir, а не -exec? - person anubhava; 07.02.2014
comment
Конечно, я уверен, что я скопировал/вставил ту же команду, которая работала на моем локальном компьютере. Как ни странно, на сервере это дает результат, который я показал вам выше. - person pzd060; 08.02.2014
comment
Это странно, так как я проверил это снова. Вы также можете попробовать: find . -name '*.jpg' -exec bash -c 'd="${1%/*}"; mv "$1" "$d/$d-${1##*/}"' - '{}' \; команда - person anubhava; 08.02.2014

Чтобы получить имя папки файла, вы можете сделать $(basename $(dirname ${FILE})), где ${FILE} — это путь, который может быть относительным, но должен содержать хотя бы одну папку перед именем файла в ней. Это не должно быть проблемой с find. Если это так, просто запустите его из одного каталога вверх.

find . -name '*.jpg' -exec sh -c 'mv "$0" "$(basename $(dirname $0))-${0%.JPG}$.jpg"' {} \;

Или, если у вас есть файлы JPEG в текущем каталоге:

find ../<dirname> -name '*.jpg' -exec sh -c 'mv "$0" "$(basename $(dirname $0))-${0%.JPG}$.jpg"' {} \;
person Mad Physicist    schedule 07.02.2014
comment
Я пробую это в текущем каталоге (в целях тестирования), и когда я запускаю его, у меня есть mv: переименовать ../D44203/9.jpg в D44203/../D44203/9.jpg$.jpg: Нет такого файла или каталог - person pzd060; 07.02.2014
comment
@pzd060. Извините, не последовал собственному совету. Я просто заменил косую черту на тире. - person Mad Physicist; 07.02.2014