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


Получить помощь и пообщаться с другими пользователями Ubuntu можно
на irc канале #ubuntu-ru в сети Freenode
и в Jabber конференции ubuntu@conference.jabber.ru

Автор Тема: bash вывод команды в массив  (Прочитано 12708 раз)

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

Оффлайн Bloodlettinger

  • Автор темы
  • Новичок
  • *
  • Сообщений: 24
    • Просмотр профиля
bash вывод команды в массив
« : 05 Января 2011, 22:22:17 »
есть большая задача, застопорился на выводе команды ls в массив
#!/bin/bash
catalog_osnovnoy=/home/bloodlettinger/test/share

cd $catalog_osnovnoy
declare -a dir_mesyac=$(ls -1)

for ((i=0;i<${#dir_mesyac[@]};i++));do
cd $catalog_osnovnoy/${dir_mesyac[$i]}
declare -a dir_den=$(ls);
echo ${dir_mesyac[$i]}
echo $dir_den
done

exit 0
сейчас пытался написать вывод ls  в массив, потом пройтись по этим каталогам и в каждом из них выполнить действия, для проверки эхом вывод делаю. в этом коде в первый элемент массива  записывается весь вывод команды, т.е все каталоги в одну переменную пишутся, а надо что бы каждый каталог в новой переменной массива. Для этого надо делать цикл с фильтром вывода ls по пробелам или как то проще можно? если не затруднит, приведите плз пример рабочего кода похожего, гугл мне не помог (

Пользователь решил продолжить мысль 06 Января 2011, 00:06:21:
порылся по форуму, из подобных конвееров повыбирал что то похожее написал вот так:
declare -a dir_mesyac
i=0; ls | while read; do ${dir_mesyac[i++]}=$REPLY; done
на выход получил вот такое:
строка 8: =dir_mesyac[i]: команда не найдена
строка 8: =[i]: команда не найдена
строка 8: =месяц_01: команда не найдена
строка 8: =месяц_02: команда не найдена
строка 8: =месяц_03: команда не найдена
подскажите почему присваивание элементам массива не срабатывает? в $REPLY то, как видно из выхода, построчно запись идет норм
« Последнее редактирование: 06 Января 2011, 00:06:21 от Bloodlettinger »

Оффлайн Mam(O)n

  • Старожил
  • *
  • Сообщений: 5855
    • Просмотр профиля
Re: bash вывод команды в массив
« Ответ #1 : 06 Января 2011, 01:36:32 »
IFS=$'\n' array=( $(ls -l) )
for rec in ${array[@]}; do
    echo $rec
done

Оффлайн smaharbA

  • Участник
  • *
  • Сообщений: 220
    • Просмотр профиля
Re: bash вывод команды в массив
« Ответ #2 : 06 Января 2011, 10:29:20 »
для этого как бы find ... -exec чегото {} чемуто \; существует
Я конечно далек от мысли...(с)

Оффлайн ArcFi

  • Старожил
  • *
  • Сообщений: 15189
    • Просмотр профиля
    • aetera.net
Re: bash вывод команды в массив
« Ответ #3 : 06 Января 2011, 10:41:11 »
i=0; ls | while read; do ${dir_mesyac[i++]}=$REPLY; done
i=0 ; ls | while read ; do d[i]="$REPLY" ; ((i++)) ; done
Но зачем?

Оффлайн Bloodlettinger

  • Автор темы
  • Новичок
  • *
  • Сообщений: 24
    • Просмотр профиля
Re: bash вывод команды в массив
« Ответ #4 : 06 Января 2011, 11:38:30 »
еще полистал форумы, в итоге все заработало, сделал так:
#!/bin/bash
catalog_osnovnoy=/home/bloodlettinger/test/share
catalog_sjato=/home/bloodlettinger/test/sjato
cd $catalog_osnovnoy

declare -a dir_mesyac=$(ls)
declare -a dir_den
declare -a files
for dir_mesyac in ${dir_mesyac[@]}
do
echo $dir_mesyac
cd $catalog_osnovnoy/$dir_mesyac
dir_den=$(ls)
for dir_den in ${dir_den[@]}
do
echo $dir_den
cd $catalog_osnovnoy/$dir_mesyac/$dir_den
files=$(ls)
for files in ${files[@]}
do
echo $files
if [[ ! ( -f $catalog_sjato/$dir_mesyac/$dir_den/$files ) ]]
then
if [[ ! ( -f $catalog_sjato/$dir_mesyac ) ]]
then mkdir $catalog_sjato/$dir_mesyac
fi
if [[ ! ( -f $catalog_sjato/$dir_mesyac/$dir_den ) ]]
then mkdir $catalog_sjato/$dir_mesyac/$dir_den
fi
(lame -b 64 $files $catalog_sjato/$dir_mesyac/$dir_den/$files)
fi
done
done
done

exit 0

это мой первый скрипт на баше, поэтому насчет красоты не задумывался. Друг тоже советовал сделать через find, но тогда бы пришлось строку разбирать на каталоги что бы создавать новые в папке sjato , а так все эти каталоги уже есть. Если кто подскажет как это сделать более красиво и изящно - буду благодарен, видимо часто теперь придется башем пользоваться

Оффлайн ArcFi

  • Старожил
  • *
  • Сообщений: 15189
    • Просмотр профиля
    • aetera.net
Re: bash вывод команды в массив
« Ответ #5 : 06 Января 2011, 12:28:03 »
1) дублирование дерева каталогов:
rsync -rt -f '-! */' $SRC_DIR $DST_DIR
2) пакетная обработка файлов:
find ... -exec чегото {} чемуто \;

Этого должно быть достаточно для решения такой задачи.
Впрочем, достаточно даже последнего.
« Последнее редактирование: 06 Января 2011, 12:30:03 от ArcFi »

Оффлайн Mam(O)n

  • Старожил
  • *
  • Сообщений: 5855
    • Просмотр профиля
Re: bash вывод команды в массив
« Ответ #6 : 06 Января 2011, 14:31:51 »
в итоге все заработало, сделал так:
Задумайся, а что будет, если в имени файла окажется пробел...

Оффлайн Bloodlettinger

  • Автор темы
  • Новичок
  • *
  • Сообщений: 24
    • Просмотр профиля
Re: bash вывод команды в массив
« Ответ #7 : 06 Января 2011, 14:55:02 »
в итоге все заработало, сделал так:
Задумайся, а что будет, если в имени файла окажется пробел...
там точно пробела не будет, все файлы по шаблону обозваны ) пасип за замечание

Оффлайн Bloodlettinger

  • Автор темы
  • Новичок
  • *
  • Сообщений: 24
    • Просмотр профиля
Re: bash вывод команды в массив
« Ответ #8 : 27 Января 2011, 01:02:35 »
в процессе допила скрипта наступил на очередные грабли, сам обойти не могу. все подробненько в коментах кода расписал
#!/bin/bash
#каталог в котором по дефолту находится все файло, каталоги типа месяц1день1файл1.mp3
dir_share=/home/bloodlettinger/test/share
#сюда сваливаются сжатые файлы
dir_sjato=/home/bloodlettinger/test/sjato
#сюда сваливаются файлы из каталожа сжато, при достижении размера каталога 4гб, формируется исошник
dir_cdrew=/home/bloodlettinger/test/cdrew
#каталог с образами дисков
dir_iso=/home/bloodlettinger/test/iso

# из соответствующих файлов читаем название каталога месяца дня и файла, которые были обработанны поседней сессией этого же скрипта
# т.е например я запустил в понедельник скрипт, он обработал сколько то файлов
# необходимо, что бы при запуске в среду он не обрабатывал все файло повторно, а только с последнего. в фалы скопипастил руками для эксперемента месяц2 день3 файл4.mp3
# все без пробелов
read default_mesyac < /$dir_sjato/default_mesyac
read default_den < /$dir_sjato/default_den
read default_file < /$dir_sjato/default_file

# проверка чтения из файлов
#echo $default_mesyac $default_den $default_file

# делаю 3 массива с каталогами месяцев дней и файлов, и поочереди все пролистываю
declare -a dir_mesyac=$(ls $dir_share)
declare -a dir_den
declare -a files
for dir_mesyac in ${dir_mesyac[@]}
do
echo $dir_mesyac
dir_den=$(ls $dir_share/$dir_mesyac)
for dir_den in ${dir_den[@]}
do
echo $dir_den
IFS=$'
' files=( $(ls -l $dir_share/$dir_mesyac/$dir_den) )
for files in ${files[@]}
do

files_name=$(echo $files | awk '{print $8}')

# поиск последнего обработанного файла прошлой сессией
if [ "$file_name" = "$default_file" ];
then
i=1
else
i=0
fi
echo  $files_name $default_file $i
# по логике все описаное дальше сейчас не сильно важно, необходимо правильно обработать сравнение, после того
# как удачно пройдет сравнение месяц = дефаултмесяц и день = дефаулт день и файл = дефаулт файл
# я выставляю i=1. далее еще условие и если i=0 то брекаю этот цикл, если =1 то выполняю все описанное ниже и все хорошо
# вот тут то и грабли, сравнение никак не срабатывает, пробовал в () и (()) и [] и [[]] , на всякий случай пробовал их сравнивать как
# числа, пробовал как строки, либо выдает ошибки либо говорит что они неравны всегда, что приходит на вывод опишу следующим блоком

if [[ ! ( -f $dir_sjato/$dir_mesyac/$dir_den/$files_name ) ]]
then
if [[ ! ( -d $dir_sjato/$dir_mesyac ) ]]
then mkdir $dir_sjato/$dir_mesyac
fi
if [[ ! ( -d $dir_sjato/$dir_mesyac/$dir_den ) ]]
then mkdir $dir_sjato/$dir_mesyac/$dir_den
fi
#(lame -b 64 $files_name $dir_sjato/$dir_mesyac/$dir_den/$files_name)
fi
size=$(du -s $dir_cdrew | awk '{print $1;}')
#echo $size
if [[ $size -lt 70000 ]]
then
if [[ ! ( -d $dir_cdrew/$dir_mesyac ) ]]
then $(mkdir $dir_cdrew/$dir_mesyac)
fi
if [[ ! ( -d $dir_cdrew/$dir_mesyac/$dir_den ) ]]
then $(mkdir $dir_cdrew/$dir_mesyac/$dir_den)
fi
#$(mv $dir_sjato/$dir_mesyac/$dir_den/$files_name $dir_cdrew/$dir_mesyac/$dir_den/)
else
#$(mkisofs -joliet-long -r -v -o $dir_iso/$(date +%d%m%y%H%M%S).iso $dir_cdrew )
#$(rm -rf $dir_cdrew/*)
if [[ ! ( -d $dir_cdrew/$dir_mesyac ) ]]
then $(mkdir $dir_cdrew/$dir_mesyac)
fi
if [[ ! ( -d $dir_cdrew/$dir_mesyac/$dir_den ) ]]
then $(mkdir $dir_cdrew/$dir_mesyac/$dir_den)
fi
#$(mv $dir_sjato/$dir_mesyac/$dir_den/$files_name $dir_cdrew/$dir_mesyac/$dir_den/)
fi
done
done
done



#growisofs -Z /dev/cdrom=/home/bloodlettinger/test/iso/070111034025.iso
#eject /dev/cdrom

exit 0

вывод скрипта
bloodlettinger@bloodlettinger-pc:~/Рабочий стол$ bash record.sh
месяц_01
день_01
04_start_00.mp3 0
00_start_00.mp3 04_start_00.mp3 0
01_start_00.mp3 04_start_00.mp3 0
02_start_00.mp3 04_start_00.mp3 0
03_start_00.mp3 04_start_00.mp3 0
04_start_00.mp3 04_start_00.mp3 0
05_start_00.mp3 04_start_00.mp3 0
06_start_00.mp3 04_start_00.mp3 0
07_start_00.mp3 04_start_00.mp3 0
08_start_00.mp3 04_start_00.mp3 0
09_start_00.mp3 04_start_00.mp3 0
10_start_00.mp3 04_start_00.mp3 0
11_start_00.mp3 04_start_00.mp3 0
12_start_00.mp3 04_start_00.mp3 0
13_start_00.mp3 04_start_00.mp3 0
14_start_00.mp3 04_start_00.mp3 0
15_start_00.mp3 04_start_00.mp3 0
16_start_00.mp3 04_start_00.mp3 0
17_start_00.mp3 04_start_00.mp3 0
18_start_00.mp3 04_start_00.mp3 0
19_start_00.mp3 04_start_00.mp3 0
20_start_00.mp3 04_start_00.mp3 0
21_start_00.mp3 04_start_00.mp3 0
22_start_00.mp3 04_start_00.mp3 0
23_start_00.mp3 04_start_00.mp3 0
месяц_02 04_start_00.mp3 0
месяц_03 04_start_00.mp3 0
день_02
04_start_00.mp3 0
00_start_00.mp3 04_start_00.mp3 0
01_start_00.mp3 04_start_00.mp3 0
02_start_00.mp3 04_start_00.mp3 0
03_start_00.mp3 04_start_00.mp3 0
04_start_00.mp3 04_start_00.mp3 0
05_start_00.mp3 04_start_00.mp3 0
06_start_00.mp3 04_start_00.mp3 0
07_start_00.mp3 04_start_00.mp3 0
08_start_00.mp3 04_start_00.mp3 0
09_start_00.mp3 04_start_00.mp3 0
10_start_00.mp3 04_start_00.mp3 0
11_start_00.mp3 04_start_00.mp3 0
12_start_00.mp3 04_start_00.mp3 0
13_start_00.mp3 04_start_00.mp3 0
14_start_00.mp3 04_start_00.mp3 0
15_start_00.mp3 04_start_00.mp3 0
16_start_00.mp3 04_start_00.mp3 0
17_start_00.mp3 04_start_00.mp3 0
18_start_00.mp3 04_start_00.mp3 0
19_start_00.mp3 04_start_00.mp3 0
20_start_00.mp3 04_start_00.mp3 0
21_start_00.mp3 04_start_00.mp3 0
22_start_00.mp3 04_start_00.mp3 0
23_start_00.mp3 04_start_00.mp3 0
день_03
04_start_00.mp3 0
00_start_00.mp3 04_start_00.mp3 0
01_start_00.mp3 04_start_00.mp3 0
02_start_00.mp3 04_start_00.mp3 0
03_start_00.mp3 04_start_00.mp3 0
04_start_00.mp3 04_start_00.mp3 0
05_start_00.mp3 04_start_00.mp3 0
06_start_00.mp3 04_start_00.mp3 0
07_start_00.mp3 04_start_00.mp3 0
08_start_00.mp3 04_start_00.mp3 0
09_start_00.mp3 04_start_00.mp3 0
10_start_00.mp3 04_start_00.mp3 0
11_start_00.mp3 04_start_00.mp3 0
12_start_00.mp3 04_start_00.mp3 0
13_start_00.mp3 04_start_00.mp3 0
14_start_00.mp3 04_start_00.mp3 0
15_start_00.mp3 04_start_00.mp3 0
16_start_00.mp3 04_start_00.mp3 0
17_start_00.mp3 04_start_00.mp3 0
18_start_00.mp3 04_start_00.mp3 0
19_start_00.mp3 04_start_00.mp3 0
20_start_00.mp3 04_start_00.mp3 0
21_start_00.mp3 04_start_00.mp3 0
22_start_00.mp3 04_start_00.mp3 0
23_start_00.mp3 04_start_00.mp3 0
день_04
04_start_00.mp3 0
00_start_00.mp3 04_start_00.mp3 0
01_start_00.mp3 04_start_00.mp3 0


т.е во всех случаях сравнение неудачно, хотя в каждом дне есть файл с нужным именем
04_start_00.mp3 04_start_00.mp3 0
на выводе в каталоге каждого дня
с чем это связанно?

Пользователь решил продолжить мысль 27 Января 2011, 01:24:50:
http://rus-linux.net/MyLDP/HOWTO-ru/Bash-Progr-Intro-HOWTO/Bash-Prog-Intro-HOWTO-11.html
а прочитав там один пример вообще мозк встал
11.2 Примеры сравнения строк

Сравнение двух строк.
        #!/bin/bash
        S1='string'
        S2='String'
        if [ $S1=$S2 ];
        then
                echo "S1('$S1') не равна to S2('$S2')"
        fi
        if [ $S1=$S1 ];
        then
                echo "S1('$S1') равна to S1('$S1')"
        fi
строки разные а резльутат почему то в обоих случаях true, мало того  ради эксперемента сделал S1='smasdkjf' , а S2='sjkdbwed' , и они так же , в обоих случаях оказались равны.
« Последнее редактирование: 27 Января 2011, 01:24:50 от Bloodlettinger »

Оффлайн Mam(O)n

  • Старожил
  • *
  • Сообщений: 5855
    • Просмотр профиля
Re: bash вывод команды в массив
« Ответ #9 : 27 Января 2011, 11:30:17 »
if [ "$file_name" = "$default_file" ];
then
i=1
else
i=0
fi
echo  $files_name $default_file $i
Прочвуствуй разницу между $file_name и $files_name

       if [ $S1=$S2 ];
Оператор сравнения должен быть обрамлён пробелами и т.п. И не забывай переменные обрамлять кавычками, на всякий пожарный.
« Последнее редактирование: 27 Января 2011, 11:32:44 от Mam(O)n »

Оффлайн alexander.pronin

  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: bash вывод команды в массив
« Ответ #10 : 27 Января 2011, 11:39:21 »
Смотреть все скрипты не хочу, но предложу использовать методику, которая позволяет не сломать мозг.

Ведите лог проблемного места в файле.
Чтобы увидеть скрытые символы (например пробелы), экранируйте значения какими-то символами, тогда уже будет место приложения мозга.

ЗЫ. Подумайте о применении питона, если работа не конечна (типа сделал и забыл).
« Последнее редактирование: 27 Января 2011, 11:42:19 от alexander.pronin »

Оффлайн Bloodlettinger

  • Автор темы
  • Новичок
  • *
  • Сообщений: 24
    • Просмотр профиля
Re: bash вывод команды в массив
« Ответ #11 : 27 Января 2011, 12:53:08 »
Цитировать
Прочвуствуй разницу между $file_name и $files_name
Вы спаситель :) все дело в очепятке. Низкий вам поклон.
Цитировать
ЗЫ. Подумайте о применении питона, если работа не конечна (типа сделал и забыл).
задумался, но этот сктипт уже принципиально хочется добить на баше.

 

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