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


Хотите сделать посильный вклад в развитие Ubuntu и русскоязычного сообщества?
Помогите нам с документацией!

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

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

Оффлайн sherba800

  • Автор темы
  • Любитель
  • *
  • Сообщений: 63
    • Просмотр профиля
Имеется следующий скрипт:

#!/bin/bash

i=1
for file in `ls *.jpg | sort -g`
do
        j=$( printf "%04d" "$i" )
        mv "$file" "$j.jpg"
        (( i++ ))
done

Он тупо сортирует картинки и нумерует их последовательно по маске из четырёх цифр начиная с "0001...0002...0003...".
Задача: есть много директорий с изображениями, в них поддиректории и т.д. Нужно каким-то образом заставить скрипт пройтись по всем директориям и обработать их скриптом выше, но так, чтобы в каждой директории имена файлов начинались с "0001". Как можно организовать подобное на Bash?

Оффлайн victor00000

  • Старожил
  • *
  • Сообщений: 15568
  • Глухонемой (Deaf)
    • Просмотр профиля
find /папка -bame "*.jpg" | sort > /tmp/file.txt
l=`cat /tmp/file.txt | wc -l`

for ((i=1;i<=l;i++))
do
file=`cat /tmp/file.txt | head -$i | tail -1`
...

j=$( printf "%04d" "$i" )
mv "$file" "$j.jpg"
....
done
Wars ~.o

Оффлайн jura12

  • Старожил
  • *
  • Сообщений: 1418
  • 20.04
    • Просмотр профиля
Связку find и xargs
сопротивление бесполезно

Оффлайн Peter_I

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

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 6017
  • Windows10, i3wm on Debian9, Manjaro20.0
    • Просмотр профиля
Код: (bash) [Выделить]
find <full_path_to_dir> -type d -exec bash -c '
    cd "$0"
    i=1
    for file in *.jpg ; do
        mv "$file" $(printf "%04d.jpg" $i)
        ((i++))
    done
    cd -
' {} \;
« Последнее редактирование: 23 Мая 2016, 13:58:10 от Azure »
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн Cxms

  • Активист
  • *
  • Сообщений: 407
    • Просмотр профиля
Azure,
зачем
cd -после цикла?

Оффлайн victor00000

  • Старожил
  • *
  • Сообщений: 15568
  • Глухонемой (Deaf)
    • Просмотр профиля
Cxms, рановато.
Wars ~.o

Оффлайн Cxms

  • Активист
  • *
  • Сообщений: 407
    • Просмотр профиля
Для каждой дир вызывать новый проц. баша - не гуд.
Лучше так:

IFS=$'\n'
for D in $(find "Start_dir" -type d)
do
cd "$D"
        i=1
        for F in *.jpg ; do mv "$F" $(printf "%04d.jpg" $i); ((i++)); done
done

Оффлайн victor00000

  • Старожил
  • *
  • Сообщений: 15568
  • Глухонемой (Deaf)
    • Просмотр профиля
Cxms,
Цитировать
for file in `ls *.jpg | sort -g`
если
1:L~$ ls ~/paint/2*/*.png
bash: /bin/ls: Слишком длинный список аргументов
1:L~$



Пользователь добавил сообщение 23 Мая 2016, 15:29:34:
Cxms,
Цитировать
for D in $(find "Start_dir" -type d)
поднимался верх память.
« Последнее редактирование: 23 Мая 2016, 15:29:34 от victor00000 »
Wars ~.o

Оффлайн Cxms

  • Активист
  • *
  • Сообщений: 407
    • Просмотр профиля
С сортом файлов в каждой дир:

IFS=$'\n'
for D in $(find "Start_dir" -type d)
do
cd "$D"
        i=1
        for F in $(find -maxdepth 1 -type f -iname "*.jpg" | sort -g)
do
mv "$F" $(printf "%04d.jpg" $i)
((i++))
done
done
« Последнее редактирование: 23 Мая 2016, 17:11:54 от Cxms »

Оффлайн victor00000

  • Старожил
  • *
  • Сообщений: 15568
  • Глухонемой (Deaf)
    • Просмотр профиля
Cxms, отлично.
sherba800, этот.


Пользователь добавил сообщение 23 Мая 2016, 16:16:24:
Cxms,
#!/bin/bash

for d in ~/*/ ~/*/*/ ~/*/*/*/ ~/*/*/*/*/
do
l=1
for f in ${d}*.png
do
echo "$f -> $d`printf \"%04d\" $l`.png"
((l++))
done
done

кто ещё победим? )))
Wars ~.o

Оффлайн sherba800

  • Автор темы
  • Любитель
  • *
  • Сообщений: 63
    • Просмотр профиля
Спасибо всем, кто ответил. Принцип понятен теперь.
Cxms, Здорово, судя по коду должно работать, но постоянно выдаёт ошибку для каждой папки, которую найдёт, пример для одной:
/home/sherbakov/counter_beta.sh: line 6: cd: ./Images/Untitled Folder (3rd copy): No such file or directoryХотя папка есть такая, в ней файлы. Я так понял дело в том, что cd не хочет монтировать папку с пробелами в имени файлов, нужно экранировать. Но для чего тогда переменная IFS=$'\n' и почему cd её не воспринимает?
« Последнее редактирование: 23 Мая 2016, 19:58:53 от sherba800 »

Оффлайн victor00000

  • Старожил
  • *
  • Сообщений: 15568
  • Глухонемой (Deaf)
    • Просмотр профиля
Cxms, вот.
Цитировать
for D in $(find "Start_dir" -type d)
там пробел.
for D in Загрузки Рабочий стол
sherba800,
for D in $(find "Start_dir" -type d | tr ' ' '\\')
Wars ~.o

Оффлайн Cxms

  • Активист
  • *
  • Сообщений: 407
    • Просмотр профиля
victor00000,
Нет, экранировать не надо. IFS=$'\n' - разделитель аргументов = новая строка. (работает)

sherba800,
Вместо Start_dir нужно вставить абсолютный (от корня) путь до директории которая содержит поддиректории с файлами jpg.

Пользователь добавил сообщение 23 Мая 2016, 21:00:52:
Можно и без cd:

IFS=$'\n'
for D in $(find "Start_dir" -type d)
do
        i=1
        for F in $(find "$D" -maxdepth 1 -type f -iname "*.jpg" | sort -g)
        do
                mv "$F" "$(dirname "$F")/$(printf "%04d.jpg" $i)"
                ((i++))
        done
done
« Последнее редактирование: 23 Мая 2016, 21:08:28 от Cxms »

Оффлайн victor00000

  • Старожил
  • *
  • Сообщений: 15568
  • Глухонемой (Deaf)
    • Просмотр профиля
1:L~$ for d in $(find Р*л -type d);do echo $d;doneРабочий
стол
Рабочий
стол/Документы
Рабочий
стол/Новый
Рабочий
стол/Эра
динозавров
1:L~$


Пользователь добавил сообщение 23 Мая 2016, 21:12:18:
1:L~$ for d in Рабоч*;do echo $d;done
Рабочий стол
1:L~$
вот лучше.
« Последнее редактирование: 23 Мая 2016, 21:12:18 от victor00000 »
Wars ~.o

 

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