LINUX.ORG.RU

Bash. Суммировать и агрегировать вывод цикла

 ,


0

2

Есть скрипт который выводит кол-во строк\путь\дату:

month="$(date --date='1 day ago' +%y%m)"

for catalog in $(find ./ -type d -name "$month")
   do 
    sum=0
   find $catalog -type f -name "*.z" | while read FN 
   do   
    sum=$((sum+$(zcat $FN | awk 1 | wc -l)))
    echo "no of lines $sum;source $(find $catalog -type d );data $(date +"%d-%m-%Y %T")"
    done
done

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

no of lines 3;source ./AXE/CNA5/LBN/2211;data 01-12-2022 17:35:49
no of lines 6;source ./AXE/CNA5/LBN/2211;data 01-12-2022 17:35:50
no of lines 9;source ./AXE/CNA5/LBN/2211;data 01-12-2022 17:35:50
no of lines 13;source ./AXE/CNA5/LBN/2211;data 01-12-2022 17:35:51
no of lines 3;source ./AXE/TELLIN/2211;data 01-12-2022 17:35:51
no of lines 7;source ./AXE/TELLIN/2211;data 01-12-2022 17:35:51

Как сделать чтобы выводил

no of lines 13;source ./AXE/CNA5/LBN/2211;data 01-12-2022 17:35:51
no of lines 7;source ./AXE/TELLIN/2211;data 01-12-2022 17:35:51

Логика этого безумия ускользает от моего понимания.

Кроме того:

awk 1

echo $(find $catalog -type d )

в том же echo вложенные кавычки (оно у тебя работает правильно?)

futurama ★★★★★
()
Последнее исправление: futurama (всего исправлений: 1)
Ответ на: комментарий от Entmatix

А почему вот этот не работает? Вроде же все правильно

month="$(date --date='1 day ago' +%y%m)"
while read catalog 
do
	sum=0
	while read lines 
	do ((sum+=lines))
	done < <( zgrep -ch . "$catalog")
	echo "no of lines $sum;source $catalog;data $(date +"%d-%m-%Y %T")"
done < <(find $(find ./ -type d -name "$month" ) -type f -name "*.z")

Передаю в цикл в переменную catalog имя файла в директории

< <(find $(find ./ -type d -name "$month" ) -type f -name "*.z")

Потом считаю кол-во строк do ((sum+=lines)) из файла done < <( zgrep -ch . "$catalog") Причем если захожу в какой нибудь каталог где лежит файл и пишу

sum=0
file="./3.z"
while read lines 
do ((sum+=lines))
done < <( zgrep -ch . "$file")
echo $sum

то работает, получается дело в первом цикле while read catalog и обработке < <(find $(find ./ -type d -name "$month" ) -type f -name "*.z")

krdgroup
() автор топика
Ответ на: комментарий от krdgroup

Опиши словами что скрипт делает

1. Берет вчерашний  ГодМесяц (YYMM)
2. в цикле обходит все директории YYMM
3. считает строки в .z файлах и накапливает их кол-во (сумму всех строк всех файлов)
4. непонятно: echo "no of lines $sum;source $(find $catalog -type d );data $(date +"%d-%m-%Y %T")"

4 непонятно почему это во внутреннем цикле выводится много раз


должно быть:

 done
 echo "no of lines: $sum; source $catalog; datе $(date +'%d-%m-%Y %T')"   
done
futurama ★★★★★
()
Последнее исправление: futurama (всего исправлений: 4)
Ответ на: комментарий от futurama
#записываю в переменную ид вчерашнего год\месяц чтобы осуществлять поиск по этому названию папки текущего или предыдущего месяца
month="$(date --date='1 day ago' +%y%m)"
#в цикле обходит все директории YYMM
while read catalog 
do
#кол-во строк в файле ставим=0
	sum=0
#в цикле обходит все строки в каждом файле
	while read lines 
#считает строки в .z файлах и накапливает их кол-во (сумму всех #строк всех файлов)
	do ((sum+=lines))
#передаем в цикл кол-во строк из $catalog
	done < <( zgrep -ch . "$catalog")
	echo "no of lines $sum;source $catalog;data $(date +"%d-%m-%Y %T")"
# передаю в цикл названия и путь к файлам
done < <(find $(find ./ -type d -name "$month" ) -type f -name "*.z")

Получается ошибка здесь? - done < <( zgrep -ch . "$catalog") т.е. он #считает строки в .z файлах и накапливает их кол-во do ((sum+=lines)) и как бы уже передает количество в цикл - done < <( zgrep -ch . "$catalog")

krdgroup
() автор топика
Ответ на: комментарий от krdgroup

Я так толком и не понял что ты хочешь посчитать и вывести

вроде так

month="$(date --date='yesterday' +%y%m)"
find ./ -type d -name "$month" | while read catalog; do
  sum=$(find $catalog -type f -name '*.z' -exec zcat + | wc -l)
  echo "no of lines $sum; source $catalog; date $(date +'%d-%m-%Y %T')"
done
futurama ★★★★★
()
Последнее исправление: futurama (всего исправлений: 1)
Ответ на: комментарий от vinvlad

Вместо while-цикла нужно подставить в качестве pipe-элемента Subshell-блок:

Ну у ТС-а идея была правильнее, for dir in $(find -type d ...), другое дело, раз find всё равно у него проходит по всем каталогам без ограничения вложенности, то и список файлов достаточно получить как for file in «$dir»/*.z и не мучиться с субшелами и прочими read.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от vodz

Речь-то не о том, как оптимальнее find использовать - я просто показал, как в отдельном шаге пайпа можно выполнять цепочку из нескольких bash-директив, чего явно не знал ТС (в суть задачи я особо не вникал).

vinvlad ★★
()
Ответ на: комментарий от vinvlad

как в отдельном шаге пайпа можно выполнять цепочку из нескольких bash-директив

В bash это особо не нужно, так как есть < (cmd), что тут уже тоже подсказали, а сабшел он хорош для тяп-ляп: смастерили цепочку пайпов, получили вывод и успокоились, а как только приходится реально делать скрипты чуть более умные, то вдруг оказывается, что сабшелы та еще неудобная фигня.

vodz ★★★★★
()
Ответ на: комментарий от vodz

… В bash это особо не нужно

Ну, это сугубо личная точка зрения :) Что нужно/не нужно - это определяется конкретной задачей. Кстати, < (cmd) - это тоже код, выполняемый в сабшеле, а cmd внутри - пайп :)
Хотя, конечно, основную логику лучше выполнять в основном процессе, поскольку менять переменные основного процесса в сабшеле невозможно. Собственно, это и есть основное ограничение для кода, выполняемого в сабшеле.

vinvlad ★★
()
Ответ на: комментарий от vinvlad

это тоже код, выполняемый в сабшеле,

Безусловно, но это используется для входных данных, потому не мешают оперировать с выходным результатом, особенно после его завершения.

vodz ★★★★★
()
Ответ на: комментарий от futurama

А тут вместо + в -exec zcat + что то подставлять надо? Сейчас пишет:

find: missing argument to `-exec'
no of lines 0; source ./AXE/CNA5/LBN/2212; date 05-12-2022 08:57:55
find: missing argument to `-exec'
no of lines 0; source ./AXE/TELLIN/2212; date 05-12-2022 08:57:56

krdgroup
() автор топика
Ответ на: комментарий от vinvlad

Скрипт должен считать количество строк во всех файлах дочерних каталогов которые имеют название текущего или предыдущего месяца в зависимости от текущей даты (если 1 число то предыдущего месяца если не первое то текущий), причем кол-во дочерних каталогов и их названия могут меняться, есть только корневой каталог где лежит скрипт и папки с ид месяца 2212,2211,2210 итп.. к примеру сейчас есть каталоги:

WORK6\AXE\CNA5\LBN\2212 - 4 файла с 3,3,3 и 4 строками
WORK6\AXE\TELLIN\2212 - в нем 2 файла с 4 и 3 строками

В результате должно выдать:

кол-во строк 13; источник WORK6\AXE\CNA5\LBN\2212; дата 5.12.22
кол-во строк 7; источник WORK6\AXE\TELLIN\2212: дата 5.12.22

Сейчас мой скрипт выдает

Количество записей 3;Источник ./AXE/CNA5/LBN/2212;Дата 05-12-2022
Количество записей 3;Источник ./AXE/CNA5/LBN/2212;Дата 05-12-2022
Количество записей 3;Источник ./AXE/CNA5/LBN/2212;Дата 05-12-2022
Количество записей 4;Источник ./AXE/CNA5/LBN/2212;Дата 05-12-2022
Количество записей 3;Источник ./AXE/TELLIN/2212;Дата 05-12-2022
Количество записей 4;Источник ./AXE/TELLIN/2212;Дата 05-12-2022

Я ваш попробовал выполнить он выводит результат:

no of lines 36; source .
./AXE
./AXE/CNA5
./AXE/CNA5/LBN
./AXE/CNA5/LBN/2210
./AXE/CNA5/LBN/2211
./AXE/CNA5/LBN/2212
./AXE/TELLIN
./AXE/TELLIN/2212; data 05-12-2022 09:03:55

krdgroup
() автор топика
Ответ на: комментарий от futurama

А как сделать чтобы если в файле в конечной строке не было символа перевода строки (Enter) чтобы он считал эти строки? У вас скрипт выводит

no of lines 9; source ./AXE/CNA5/LBN/2212; date 05-12-2022 09:15:29
no of lines 5; source ./AXE/TELLIN/2212; date 05-12-2022 09:15:30

9 и 5, а в этих каталогах

WORK6\AXE\CNA5\LBN\2212 - 4 файла с 3,3,3 и 4 строками
WORK6\AXE\TELLIN\2212 - в нем 2 файла с 4 и 3 строками

и должно выводить 13 и 7

krdgroup
() автор топика
Ответ на: комментарий от krdgroup

у меня изначально такой скрипт был:

month="$(date --date='1 day ago' +%y%m)"

for catalog in $(find ./ -type d -name "$month")
do
	echo "Количество записей $(find $catalog -type f -name "*.z" | xargs zcat | wc -l);Источник $(find $catalog -type d );Дата $(date +"%d-%m-%Y %T")"
	 
done

Я его через while и сделал чтобы строки до конца считал только теперь немного не так считает как я в начале написал

krdgroup
() автор топика
Последнее исправление: krdgroup (всего исправлений: 1)
Ответ на: комментарий от krdgroup
month="$(date --date='yesterday' +%y%m)"
while read catalog; do
   sum=0
   while read file; do
      let sum=sum+$(zcat $file | awk 'END {print NR}')
   done <<<$(find $catalog -type f -name '*.z')
  echo "no of lines $sum; source $catalog; date $(date +'%d-%m-%Y %T')"
done <<<$(find ./ -type d -name "$month")

Наверное так.

futurama ★★★★★
()
Ответ на: комментарий от krdgroup

Я ваш попробовал выполнить …

Судя по приведенному выводу вы каким-то образом умудрились запихнуть вывод команды find в одну строку и вообще что-то не очень правильно подправили у себя.

Вообще, всё что я хотел до вас донести, это:

...
find ... | (
  sum=0
  while read FN ; do   
    sum=$(( sum + ... ))
  done
  echo "no of lines $sum; ... "
)

поскольку в стартовом топике код вообще бредовый. Полностью решать вашу конкретную задачу не входило в мои намерения.

vinvlad ★★
()
Последнее исправление: vinvlad (всего исправлений: 2)
Ответ на: комментарий от vinvlad

Да, я понял. Так работает:

month="$(date --date='1 day ago' +%y%m)"
for catalog in $(find ./ -type d -name "$month")
do 
find $catalog -type f -name "*.z" | (
  sum=0
  while read FN ; do   
    sum=$(( sum + $(zcat $FN | awk 1 | wc -l) ))
  done
  echo "no of lines $sum; source $(find $catalog -type d ); data $(date +"%d-%m-%Y %T")"
)
done

Спасибо

krdgroup
() автор топика
Ответ на: комментарий от futurama

Да, так работает

while read catalog; do
   sum=0
   while read file; do
      let sum=sum+$(zcat $file | awk 'END {print NR}')
   done <<<$(find $catalog -type f -name '*.z')
  echo "no of lines $sum; source $catalog; date $(date +'%d-%m-%Y %T')"
done <<<$(find ./ -type d -name "$month")

Спасибо

krdgroup
() автор топика