Форум русскоязычного сообщества Ubuntu


За новостями русскоязычного сообщества и Ubuntu в целом можно следить на нашей страничке в Google+

Автор Тема: Как сделать выполнение данного скрипта рекурсивно во всех подкаталогах?  (Прочитано 686 раз)

0 Пользователей и 1 Гость просматривают эту тему.

adawdp

  • Автор темы
  • Гость
2016 Jan 18; 09:37 AM; Oakville, ON, Canada.

— Существует вот такая, критикуемая по форме, но работающий безотказно в конкретной директории группа команд:
Код: Bash
  1. for file in *; do mv "$file" `echo $file | sed 's/[^.[:alnum:]]/_/g' | awk '{ print tolower($0) }'`; done
— Эта конструкция  заменяет пробелы (и пр.) в именах файлов. Обсуждалось содержательно здесь _http://www.linux.org.ru/forum/general/12139480
— Хотелось бы аналогичный результат получить рекурсивно во всех подкаталогах данного каталога. Готового рецепта в месте обсуждения нет :(
— Все мои попытки придать этой композиции рекурсивность успехом не увенчались.

— Возможно ли придать рекурсивность данной группе команд, положим как исполнение скрипта на основе данных команд во всех подкаталогах данного каталога?
— Может у кого-то есть готовое решение для данного вопроса?

Оффлайн Heider

  • Старожил
  • *
  • Сообщений: 1037
    • Просмотр профиля
А классическое построение рекурсии не подходит? Оформить этот скрипт как функцию и внутри поставить условие: если текущий файл это каталог, то вызов самой себя для этого каталога.

Оффлайн jura12

  • Старожил
  • *
  • Сообщений: 1183
  • debian 9, manjaro
    • Просмотр профиля
можно по этим схемам так или так
(Нажмите, чтобы показать/скрыть)
сопротивление бессполезно

Оффлайн alsoijw

  • Старожил
  • *
  • Сообщений: 4073
  • Fedora 25 GNOME 3 amd64
    • Просмотр профиля
adawdp, в месте * получается список файлов. Надо в наклонных кавычках ` вызывать find.
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

adawdp

  • Автор темы
  • Гость
2016 Jan 18; 10:28 AM

— Спасибо всем, концептуальные моменты я рассмотрю позже ;), а вот что-то попроще из вот такой серии никак? Я совершенно не программист, господа :(
Код: Bash
  1. find . -type d -exec supfind.sh {} +
Где supfind.sh набор приведенных команд в скрипте.

Пользователь решил продолжить мысль [time]18 Январь 2016, 19:33:53[/time]:
— Вы,alsoijw, вот так предложили попробовать?
Код: Bash
  1. for file in `find`; do mv "$file" `echo $file | sed 's/[^.[:alnum:]]/_/g' | awk '{ print tolower($0) }'`; done
— Удаляет почему-то все файлы из тренировочного  каталога.:(
« Последнее редактирование: 18 Январь 2016, 18:38:26 от adawdp »

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5661
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Стоп-стоп, коллеги!find -type f -name '*[^.[:alnum:]]*' -exec rename -n 's/[^.\/\w\xa1-\xff](?!.*\/)/_/g;s/[^\/]+$/\U$&/' {} +
« Последнее редактирование: 19 Январь 2016, 00:53:11 от Azure »
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

adawdp

  • Автор темы
  • Гость
2016 Jan 18; 12:12 PM

Azure, я Вас приветствую! К сожалению предложенный Вами вариант не работает. Дело в том, что в отдельной директории (не рекурсивно) приведенная выше группа команд взятая отсюда http://www.linux.org.ru/forum/general/12139480 работает безотказно с самыми сложными именами файлов, ну например с кнопками запуска страниц вытащенных из адресной строки браузера.
— Там решения проблемы в общем-то конкретно не предлагается, только пути решения :(  Возможно нужен вообще другой подход, но помимо пробелов нужно удалить также и всё из названия чтобы например файл можно было прочесть даже из Windows.

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5661
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
adawdp, Вы ж опытный пользователь, должны понимать что фразы «предложенный Вами вариант не работает» недостаточноupdate-alternatives --list rename?, т.к. УМВР(поправил для файлов с расширениями).
Чистый bash
Код: Bash
  1. #!/bin/bash
  2. shopt -s globstar
  3. for dir in **/
  4. do
  5.     for file in "$dir"/*
  6.     do
  7.          [ -d "$file" ] && continue # пропускает папки
  8.          path=${file%/*}
  9.          name=${file#$path/}
  10.          name=${name//[^.[:alnum:]]/_}
  11.          mv "$file" "$path/${name^^}"
  12.     done
  13. done
  14. shopt -u globstar
   
« Последнее редактирование: 18 Январь 2016, 23:32:42 от Azure »
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

adawdp

  • Автор темы
  • Гость
2016 Jan 18; 02:23 PM
Azure, я думал чуть позже расширить повествование, работа слегка мешает :) ! Считайте это явкой с повинной, я вообще на УДО (условно-досрочное освобождение) рассчитываю. А УМВР надо полагать — у меня всё работает, не сразу я догадался… :)
/usr/bin/prename #!/usr/bin/perl -w я это ещё раньше смотрел в каких то рекомендациях, потому как rename на языке perl написана, но мне одинаково почти что перл, что суахили…
— Это update-alternatives --list rename выполнил…
(Нажмите, чтобы показать/скрыть)
— Вроде есть какие-то попытки переименовывать, но почему не переименовывает непонятно. Команда, которая в начале темы работает безупречно :(
— Преобразования, произведенные этой командой в конце под спойлером.

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5661
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
adawdp,
rename -n — на посмотреть, для окончательного переименования -n убрать.
bash-скрипт тоже поправил dir —> $dir
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

adawdp

  • Автор темы
  • Гость
2016 Jan 18; 07:02 PM

Azure, может это дело бросить? Что-то задача перестала мне казаться простой… :(
Удалось на бегу поговорить с нашим приходящим программистом из всего разговора с ним я понял, что rename менее подходит для этой задачи чем sed и ещё у него какие-то сомнения по поводу ключа где присутствует „w“. Про:
Код: Text
  1.  -n, --no-act
  2.                No Action: show what files would have been renamed.

я, „тупо ;)“ забыл, а читал ведь.
— Со скриптом на bash дела обстоят лучше. Там по-моему есть шансы выправить ситуацию. Файлы переименовывает, а директории пропускает. Но я посмотрел, что вроде у Вас так задумано. Пробовал закомментировать строку, где у Вас комментарий но желаемого результата не получил.
(Нажмите, чтобы показать/скрыть)
— Да и ещё регистр может всё нужно в нижнем? А лучше может его вообще не трогать, пусть будет какой есть. Я понял что он подправляется mv "$file" "$path/${name^^}"


Пользователь решил продолжить мысль [time]19 Январь 2016, 07:11:11[/time]:
2016 Jan 18; 10:14 PM

— Директории наверное нужно отдельно менять чтобы путаница не возникла из-за путей… Или до замены файлов или после…

Код: Bash
  1. fjf@fjf-Inspiron-530s:~/Рабочий стол/z1601Jan182151$ find .  -type d | sort -r
  2. ./2016 Jan 18; 01:10 PM №001 ∗ש dir/2016 Jan 18; 01:11 PM ³ ́§°£ dir/Безымянная папка dir
  3. ./2016 Jan 18; 01:10 PM №001 ∗ש dir/2016 Jan 18; 01:11 PM ³ ́§°£ dir
  4. ./2016 Jan 18; 01:10 PM №001 ∗ש dir
  5. fjf@fjf-Inspiron-530s:~/Рабочий стол/z1601Jan182151$
— Как-то вот так наверное:
Код: Bash
  1. find .  -type d | sort -r | while read d;do mv "$d" "а тут что-то правильное нужно придумать :)";done
  2.  
— Я что-то вообще сначала упустил, что переименовывать нужно по отдельности из-за путей.
« Последнее редактирование: 19 Январь 2016, 06:15:42 от adawdp »

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5661
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Давайте разберемся с постановкой задачи
конструкция  заменяет пробелы (и пр.) в именах файлов
Потому как если надо переименовывать и директории, то надо строить или рекурсию, или делать его в 2 прохода — сначала папки, потом файлы.
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

adawdp

  • Автор темы
  • Гость
— С добрым утром! 2016 Jan 19; 08:20 AM; Oakville, ON, Canada.
— Да, действительно, задачу описал я плохо, бланкетно, так сказать, отослал к скриптукак сделать выполнение данного скрипта рекурсивно“.
— А сделать это именно с предложенным скриптом как оказалось проблематично. Приведенная в начальном сообщении группа команд производит переименование файлов и директорий только в директории где эта группа команд запущена.
— Практическое решение вопроса вижу в том, чтобы дописать  к bash скрипту вторую часть которая будет переименовывать директории. Или отдельный скрипт для переименовывания директорий. Это даже будет удобней. Можно будет применить один, другой или оба в зависимости от необходимости. Уже написанный Вами bash скрипт практически рабочий, там просто определиться с регистром переименовываемых символов "$path/${name^^}"
Идею с построением рекурсии на основе rename оставить я тут прочитал во многих местах пишут о проблемах с кодировками и всякими символами при использовании rename в разных системах.

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5661
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
adawdp, раз не нравится rename и не надо регистр менять — пробуйте
Код: Bash
  1. find -type d -name '*[^._[:alnum:]]*' -exec bash -c '
  2.    mv $0 ${0//[^.\/_[:alnum:]]/_}' {} \;
Соответственно для файлов -type f
Ну или попробовать общий
Код: Bash
  1. find -depth -name '*[^._[:alnum:]]*' -exec bash -c '
  2.    mv "$0" "$(sed ":;s|[^._/[:alnum:]]\([^/]*/\?\)$|_\1|;t" <<<"$0")"' {} \;
« Последнее редактирование: 19 Январь 2016, 21:59:20 от Azure »
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

adawdp

  • Автор темы
  • Гость
2016 Jan 19; 02:57 PM

— Спасибо Azure, последний вариант категорически идеален!
(Нажмите, чтобы показать/скрыть)
— Набор команд для замены отдельно файлов отдельно директорий что-то где-то не заработало. :(, но это чисто принципиальная теперь вещь для моих текущих задач это избыточно. Тем более скрипт для замены отдельно файлов абсолютно рабочий.
(Нажмите, чтобы показать/скрыть)
— Я сочинил вот такой вот ужас для замены директорий ( Вы так не сумеете! :) даже специально :)) Потому как невежества, Azure, в области программирования легче всего достичь путём самообразования!!! :) Программирование я не занимаюсь, а вот невежество в этой области ращу!

Код: Bash
  1. find . -type d \
  2. | sort -r \
  3. | while read d; \
  4. do mv "$d" `echo $d \
  5. | sed 's/[^.[:alnum:]]/_/g' \
  6. | awk '{ print tolower($0) }'`; \
  7. done
— Представьте себе этот кошмар даже переименовывает директории, есть некоторые странности, которые я собирался исправить после выхода на пенсию.
(Нажмите, чтобы показать/скрыть)
— Если будет время, взгляните на это всё одним глазом, дальнейшие исследования можно заканчивать это будет уже полировка, а зачем нам лишний лоск! :) Не на продажу!

 

Страница сгенерирована за 0.143 секунд. Запросов: 25.