1

Есть некоторое дерево директорий. В этих директориях, в некоторых лежат картинки с расширением .jpg. Картинки лежат по одной, то есть в одной директории лежит одна картинка. Как мне обойти это дерево и переименовать картинки на имена директорий в которых они лежат?

chopchopa
  • 225
  • 2
    Вы бы хоть определились какими средствами и под какой ОС это надо сделать. тег bash как бы говорит, что это под *nix, а cmd говорит что это под windows. А решение зависит от ОС и интерпретатора (если конечно не на питоне, который вы то же указали) ... – Mike Oct 08 '16 at 08:46
  • Я имел ввиду, что мне не важно на какой ос это делать. Чем быстрее придет решение, тем лучше. – chopchopa Oct 08 '16 at 08:56
  • Что именно у вас не получается? Или вы просто хотите, чтобы за вас написали весь скрипт? – Xander Oct 08 '16 at 09:01
  • Хотя бы подсказали, какими средствами это можно сделать - с синтаксисом bash не знаком, cmd - тем более. Пытался нагуглить, но результат ни к чему толковому не привел. – chopchopa Oct 08 '16 at 09:06
  • @AlisherMatkurbanov Если не принципиально, то почему питон, а скажем не perl. И если совсем не важно какая ОС давайте скажем на JCL это сделаем для OS/390 – Mike Oct 08 '16 at 09:06
  • Python - потому что этим яп +- владею, но думаю, если будет решение на perl, то запустить его смогу. А по поводу ос - мне тег ubuntu добавить? – chopchopa Oct 08 '16 at 09:09
  • @AlisherMatkurbanov Ну так уже лучше, если у вас на той машине стоит linux, то укажите linux и уберите cmd. вам будет наверное не удобно переносить все файлы на windows, переименовывать и переносить обратно ... – Mike Oct 08 '16 at 09:10
  • Дело в том, что у меня обратная ситуация - работаю на windows, но мне почему-то кажется, что на ubuntu bash сделать это легче и больше людей знают как это сделать на bash, поэтому добавил оба тега. – chopchopa Oct 08 '16 at 09:14
  • @AlisherMatkurbanov Ну ok, написал для linux, как вы это примените в windows не представляю. вам надо будет набор стандартных unix утилит для windows видимо искать – Mike Oct 08 '16 at 09:43

2 Answers2

4

В linux можно сделать так:

find -name "*.jpg" -type f -print | sed -e "s/\(^.*\/\([^\/]*\)\/\).*$/mv '\0' '\1\2.jpg'/" | bash

Внимание: в начале выполните команду без | bash в конце и убедитесь что сгенерились правильные команды mv.

Mike
  • 44,087
  • Перешел в корнь дерева каталогов, запустил оттуда команду. Пишет mv: missing file operand – chopchopa Oct 08 '16 at 09:57
  • @AlisherMatkurbanov Вместо mv напишите echo и посмотрите что там создается. Нормальный вывод должен выглядеть как текущее имя файла с путем и новое имя с путем – Mike Oct 08 '16 at 10:05
  • @AlisherMatkurbanov Если вывод не такой, то пробуйте частями, сначала сам find до | он должен просто выдать список всех найденных jpg, потом смотрите его уже с sed, он должен через строчку давать старое имя и новое – Mike Oct 08 '16 at 10:10
  • find и sed работают отлично, но когда пытаюсь применить их вместе с mv плохо отрабатывает, делит на пробелы, и пишет, что не может найти такие имена файлов. – chopchopa Oct 08 '16 at 10:24
  • @AlisherMatkurbanov т.е. у вас в путях содержатся пробелы и из за них возникают проблемы ? – Mike Oct 08 '16 at 10:26
  • Да, вот часть вывода. mv: cannot stat 'рыбы/Судак': No such file or directory mv: cannot stat 'грибным': No such file or directory mv: cannot stat 'Photo0046.JPG': No such file or directory – chopchopa Oct 08 '16 at 10:28
  • @AlisherMatkurbanov Сделал новый вариант. обязательно проверьте вывод перед тем как давать его bash на выполнение. Рассчитано на то, что у вас в путях и именах файлов нет одинарных кавычек в которые заключаются параметры для mv – Mike Oct 08 '16 at 10:35
  • Спасибо большое, все сработало. Спасибо, что уделили время. – chopchopa Oct 08 '16 at 10:54
  • Представьте, что у вас обнаружилась папка 123.jpg... И это, вероятно, ещё не все проблемы. Shell только кажется лёгким, а подводных камней -- мильон. – 0andriy Oct 10 '16 at 18:56
  • @AndyShevchenko Ok, пофикшено – Mike Oct 10 '16 at 19:04
  • Что будем делать с файлом *.jpg? Эта гонка может продолжаться долго, shell, повторюсь, сложный ЯП. – 0andriy Oct 10 '16 at 19:21
  • @AndyShevchenko Согласен, сложноват, вот кавычки по разному работают например. У меня параметры в одинарных кавычках, а в одинарных кавычках звездочки не транспонируются, а означают сами себя. Так что все отлично работает – Mike Oct 10 '16 at 19:45
  • Если в каталоге запуска окажется файл или каталог с .jpg, ваш скрипт поломается. Кавычки у вас не обрабатываются правильно, если они в именах файлов. Эскейпов вообще нет, а это обязательно, если думать о security... И это только начало. – 0andriy Oct 10 '16 at 19:47
  • @AndyShevchenko О том, что кавычки не должны быть в именах файлов я честно предупредил спрашивавшего в комментариях. Что бы не усложнять строку которая должна была быть выполнена один раз. Она не писалась для постоянной работы. Да, эффект .jpg в каталоге запуска я видел, когда проверял. Решил опять же не усложнять. Смысла нет. – Mike Oct 10 '16 at 19:55
3

Как обойти все подкаталоги в текущем каталоге и изменить имена *.jpg файлов на имя папки, которой картинка лежит?

На Питоне:

#!/usr/bin/env python3
"""Usage: $ rename-jpg-to-parent-dir [<root-dir>]"""
import sys
from pathlib import Path

root = Path(sys.argv[1]) if len(sys.argv) > 1 else Path.cwd()
for path in root.rglob('*/*.jpg'):
    new_path = path.with_name(path.parent.name).with_suffix(path.suffix)
    path.rename(new_path)

Пример:

$ tree -P \*.jpg
.
├── a
│   └── t.jpg
├── b
│   └── t.jpg
└── nested
    ├── c
    │   └── t.jpg
    └── t.jpg

Результат

.
├── a
│   └── a.jpg
├── b
│   └── b.jpg
└── nested
    ├── c
    │   └── c.jpg
    └── nested.jpg

Обратите внимание nested/c/t.jpg переименован в nested/c/c.jpg. Если вы хотите .jpg-файлы только в непосредственно вложенных каталогах изменять, то используйте .glob() вместо .rglob()r префикс означает «рекурсивно» в данном случае.

Скрипт принимает имя корневой директории с командной строки—по умолчанию это текущая рабочая директория.

jfs
  • 52,361