find -> grep

Автор smallNix, 29 октября 2016, 12:12:47

« назад - далее »

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

smallNix

Всем привет, не знал где написать, поэтому пошёл в этот раздел. Вроде как основы. Понадобилось мне найти во всех файлах LaTeX'а упоминание про svg. Поскольку файлы tex у меня оказались разбросаны по
разным местам я быстренько написал:
find -iname "*.tex" | grep -in 'svg'
ничего не дало, тогда я исправил на:
find -iname "*.tex" 2>&1 | grep -in 'svg'
аналогично, тогда я выкрутился так:
grep -in 'svg' `find -iname "*.tex"`
это отработало как и ожидалось. Полез в интернеты, нашёл советы типа:
find java-folder/ -name "*.java" -exec grep -l text-to-find {} \;
Это, конечно, замечательно, но хотелось бы понять почему изначальные варианты не работают?
Кто-то же должен что-то делать...

vic5710

#1
ну так и должно быть
grep ищет в файлах
в первом разе find формирует  файл имен, grep ищет в нем (а не в содержимом) выражение
второй аналогичен

for i in $(find . -name '*.tex')
do
grep 'svg' $i
done

то есть в каждом найденном файле grep ищет выражение
find лучше каталог задавать, у меня ваш вариант ругается и не ищет ничего
http://www.opennet.ru/docs/RUS/linux_base/node149.html
я пользую такой вариант для однозначности

user@debian:~$ find . -name "*.conf" 1>TMP 2>/dev/null
user@debian:~$ cat TMP | while read line; do grep -l "key=" $line; done
./.config/geany/geany.conf

ihammers

Как вариант вы можете выполнить команду grep для каждого найденного файла:
~$ find ./TeX/ -iname "*.tex" -exec grep -ls "svg" {} \;
Вывод будет показывать в каких файлах есть "svg". Без "-ls" будет вывод только строк без указания в каком файле была найдено данное совпадение.

PS: будьте осторожны с данным ключом.
Debian GNU/Linux Bookworm, LXQt/OpenBox: AMD Ryzen 5 5600G / 64Gb RAM
_______________________________
Debian GNU/Linux Bookworm, без графики: AMD Phenon X4 / 16Gb RAM
_______________________________
Debian GNU/Linux Bookworm, LXQt/OpenBox: Acer Aspire One 722 AMD C60 / 8Gb RAM / ATI HD6290

smallNix

Спасибо за ответы. Нужно немножко осознать - уместить в свою картину восприятия  ;D
Кто-то же должен что-то делать...

ZEN

Мне кажется, что в первом варианте просто не хватает xargs:
find -iname "*.tex" | xargs grep -in 'svg'
Crimea is Ukraine

smallNix

Я предполагал, что вывод find должен быть перенаправлен на вход grep. При этом под выводом я понимаю весь массив информации, оформленный в виде набора строк. А grep, в моём понимании, должен этот массив сортировать. По этой причине я не мог понять почему первый вариант не работает. Надо посмотреть исходники grep'a.
Кто-то же должен что-то делать...

alsoijw

smallNix, при конвеере grep обрабатывает stdin как текст. Как путь он обрабатывает только если указывать в аргументах.
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

vic5710

Цитата: smallNix от 29 октября 2016, 16:04:30Спасибо за ответы. Нужно немножко осознать - уместить в свою картину восприятия 
find [path] [filter] -> список файлов
grep [filter] [filename] -> строка в файле
усвоить это и легче будет

smallNix

vic5710, Я много лет работаю в Linux и могу найти решение поставленной задачи, что я и сделал в первом сообщении (третий вариант), но поскольку первый, в моём понимании - корректный, не работал, я стал подозревать, что не совсем правильно понимаю тонкости работы find, grep или каналов. Это вызвало у меня некоторый дискомфорт, поэтому я обратился за помощью.  ;D Так что меня интересовало не конкретное решение, а исправление неправильного восприятия. Но всё равно всем спасибо.
alsoijw,  так в том-то и дело. Я думал, что find помещает свой вывод как текст в stdout, потом он отправляется на вход в grep, который этот текст обрабатывает. Поскольку я grep часто использую для фильтрации строк, я не подумал, что пытаюсь его использовать не для тех строк. ;D Всё. Картина сложилась )))) Всем огромное спасибо ))
Кто-то же должен что-то делать...

alsoijw

smallNix, вот ещё пара примеров
^͜^ /mnt echo echo | echo

^͜^ /mnt echo `echo echo`
echo
^͜^ /mnt
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

smallNix

#10
alsoijw;D Ага, оно самое меня и подорвало )))

Cообщение объединено 30 октября 2016, 13:36:11

ААА!!! Всё заново! Не понимаю почему echo echo | echo не работает...  :( Блин, только с find и grep всё на свои места встало...  :'(
Кто-то же должен что-то делать...

ZEN

#11
потому что echo не работает с stdin. А вот cat работает с stdin:
$ echo echo | cat
echo

Думаю, что во всем этом помогут разобраться следующие статьи:
https://www.ibm.com/developerworks/ru/library/l-lpic1-v3-103-1/
https://www.ibm.com/developerworks/ru/library/au-spunix_pipeviewer/
Crimea is Ukraine

smallNix

ZEN, спасибо, ознакомлюсь. По поводу echo - надо проверить. В man сказано, что выводит в out. А получает? Откуда она данные может получать если всего три потока: in, out и error... Ладно, будет время - разберусь и дополню.
Кто-то же должен что-то делать...

alsoijw

smallNix, ты забыл про аргументы командной строки. stdin != args != означает не равноecho echo | echo args="" stdin="echo"
echo `echo echo` args="echo" stdin=""
На десерт предлагаю рассмотреть что куда получит при такой командеecho 1 | echo `echo 2`
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

smallNix

alsoijw;D никогда не задумывался о том, что аргумент поступает не из stdin. Почему-то я был уверен, что драйвер терминала помещает данные в stdin... Вне зависимости от того аргумент это или нет.
Кто-то же должен что-то делать...