LINUX.ORG.RU

простой вопрос по bash

 


0

2

в общем нужно посчитать общее количество найденных find файлов, решил делать так

c=0

find /usr/share -type f -a -size +4000c -a -size -4002c | while read line ; do
        (( c = c + 1 ))
        echo "$c"
done

echo -e "\n$c"

на выходе получаю 0 файлов, хотя внутри цикла счетчик работает, цикл выполняется в саб шелле?

$ ./test.sh
1
2
3
4

0

в общем нужно найденные файлы перенаправить в файл, а общее количество вывести на консоль, для этого организовал while read line, чтобы считать количество строк на выходе find. Может есть способ проще? кто-нибудь что-нибудь посоветуйте

★★★

wc -l

хотя в обоих случаях файлы, в названии которых есть '\n' обработаются неправильно.

maloi ★★★★★
()

в общем нужно найденные файлы перенаправить в файл, а общее количество вывести на консоль

В файл нужно передать имена найденных файлов или их содержимое? Если имена, то

find /usr/share -type f -a -size +4000c -a -size -4002c > found.txt
wc -l found.txt

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

ну '\n' в названиях файлов это нонсенс, так что не беда, беда в другом, мне на каждый найденный файл нужно сделать несколько вещей: напечатать в отдельной строке 1) размер в байтах, 2) путь до файла без имени файла, 3) имя файла без пути и напечатать это надо не в stdout,а в другой файл, а счетчик вывести в stdout, так что wc -l не покатит.

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

так более или менее, только у меня на каждый файл получится по 4 строчки, но это не беда.

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

1) размер в байтах, 2) путь до файла без имени файла, 3) имя файла без пути

find ... -printf '%s\t%h\t%f\n' >output.txt && wc -l output.txt
Lavos ★★★★★
()
Последнее исправление: Lavos (всего исправлений: 1)

цикл выполняется в саб шелле?

Не совсем, но у тебя в строчке есть конвеер/пайпа <|> а это в свою очередь форкает твой скрипт, тоесть то что слева от | это один процесс, то что справа - другой. Убери пайпу и замени while read на простой foreach, както так:

#!/bin/bash

OIFS="${IFS}"
NIFS="
"
IFS="${NIFS}"
files=`find /usr/share -type f -a -size +4000c -a -size -4002c`
for file in ${files}; do
        IFS="${OIFS}"

        echo "FILE [${file}]"
        (( c = c + 1 ))

        IFS="${NIFS}"
done

echo -e "\n$c"
в принциве с IFS можно не заморачиватся если нет файлов с прабелами, или внутри цикла сплитить ничего не нужно ...

Второй вариант это скинуть результат find во временный файл и потом его прочитать построчно но уже без пайпы ...

zaz ★★★★
()
Последнее исправление: zaz (всего исправлений: 1)

find ... -print0 | grep -c -z .

Для тех кто боится разных неудобных символов в именах

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

это не то, что тебе нужно. Find выдаст одну строку из-за $(find), и эта строка целиком уедет в цикл.

Т.е. будет _одна_ итерация, независимо от кол-ва файлов.

В моём примере никаких строк нет, в цикл направляется _файл_ (pipe), а не строка. Потому read читает по одной строке в каждой итерации из файла-пайпа.

emulek
()
Ответ на: комментарий от sdio

Неявно заданные конвейеры не так задалбливают?

у меня тело цикла выполняется в том же потоке, что и всё остальное. Проблема будет только если ты внутрь <() додумаешься встроить изменения переменных. Но это уже совсем упороться нужно.

emulek
()
Ответ на: комментарий от sdio

бояться надо идиотов, которые файлы называют с \n.

emulek
()
Ответ на: комментарий от gorky

там плохой пример с cat, которая ничего не делает. Если вместо cat цикл, то разница существенная.

emulek
()
Ответ на: комментарий от IvanR

Из man bash

Here Strings

A variant of here documents, the format is:

    <<<word

The word undergoes brace expansion, tilde expansion, parameter and variable expansion, command  substitution,  arithmetic  expansion, and  quote  removal.  Pathname expansion and word splitting are not performed.  The result is supplied as a single string to the command on its standard input.

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

шелл просто так \n не преобразует в строках, попробуй так

touch "$(printf "AA\nBB\nCC")"

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

ну '\n' в названиях файлов это нонсенс

Традиционное наплевательское отношение башеводов ко всему, что не ложится на их баш с пайпами. А потом им файлы -rf мешают.

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

Традиционное наплевательское отношение башеводов ко всему, что не ложится на их баш с пайпами

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

...Уходит обратно на нас поредевшая рота.
Что было — не важно, а важен лишь взорваный форт.
Мне хочется верить, что грубая наша работа
Вам дарит возможность беспошлинно видеть восход.

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

Потому что нет инструмента, который мог бы учесть все частные случаи.

Да ты же неосилятор.

find ... -print0 | while IFS= read -rd '' line; do
    # Do something with $line
done
anonymous
()
Ответ на: комментарий от anonymous

Ой, да у тебя к тому же пайпы, ну-ну. Изменить переменную попробуй внутри блока.

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

Учел один частный случай, молодец.

Какой частный случай, наркоман? Оно корректно работает со всеми возможными именами файлов.

Перечитай еще разок, на что отвечаешь.

Там ложь и псевдофилософствования.

Ой, да у тебя к тому же пайпы, ну-ну. Изменить переменную попробуй внутри блока

А пример без пайпов выше по треду мы проглядели? Ну, на, держи: http://mywiki.wooledge.org/BashFAQ/024#Workarounds

anonymous
()
Ответ на: комментарий от Deleted

Традиционное наплевательское отношение башеводов ко всему, что не ложится на их баш с пайпами.

такие файлы и в дельфине смотрятся как говно.

emulek
()
Ответ на: комментарий от Deleted

Есть же нормальные ЯП, без этого садомазо. Рубипитоны тоже делают быстро и хорошо.

сишка ещё быстрее и ещё лучше. К ней ещё autoconf, gettext и man page прикрутить можно. Только дебилы не понимают, что они потеряли, юзая баш для подсчёта числа файлов!

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

Там, где используется баш, C не всегда нужен. Т.к. часто нужно «быстро написать, сделать и забыть». А так, конечно, да. Хотя мне больше плюсы нравятся (for some values of «нравятся»).

Deleted
()
Ответ на: комментарий от anonymous

Какой частный случай, наркоман? Оно корректно работает со всеми возможными именами файлов.

Ха-ха, а вот и нет, толстячок. Что скажешь про файл и символьный линк к нему?

А пример без пайпов выше по треду мы проглядели?

За чужую юбку прячемся?

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

Т.к. часто нужно «быстро написать, сделать и забыть».

ну и на кой ляд мне тащить везде этот твой руби? Руби, питон2, питон3, руст, гоу, паскаль, brainfuck, список можно продолжать до бесконечности.

emulek
()
Ответ на: комментарий от iVS

Ха-ха, а вот и нет, толстячок.

Почему я — «толстячок»?

Что скажешь про файл и символьный линк к нему?

Скажу, что это не имеет отношения к «корректно работает со всеми возможными именами файлов». А find без -type находит все типы файлов, в т.ч. симлинки. Так что разворачивай мысль, а не виляй жопой.

За чужую юбку прячемся?

Ну, я же не должен всё писать за тебя. В треде и по моей ссылке достаточно информации, чтобы написать версию без пайпов самому.

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

Так что разворачивай мысль, а не виляй жопой.

В том-то и дело, что один файл находится дважды. Это как раз относится к «корректно работает со всеми возможными именами файлов».

В треде и по моей ссылке достаточно информации, чтобы написать версию без пайпов самому.

Слив засчитан.

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

Можешь продолжать страдать и делать час то, на что нужно 5 минут.

ты точно уверен, что на руби быстрее сделаешь, нежели я на bash'е?

emulek
()
Ответ на: комментарий от iVS

В том-то и дело, что один файл находится дважды. Это как раз относится к «корректно работает со всеми возможными именами файлов».

Нет, не относится — это два разных файла с разными именами. Иди, читай man find.

Слив засчитан.

Мда.

anonymous
()
Ответ на: помощь от websahib

что не так в моём коде?

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

что не так в моём коде?

C=0
while read
do (( C++ ))
done< <(find)

Во-первых, как уже сказали, «файлы, в названии которых есть '\n' обработаются неправильно».

Во-вторых — будут некорректно обрабатываться \ в конце имён файлов: read без -r считает

line1\
line2
за одну строку — line1line2.

Можно заменить find на find -printf '\n'.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.