Комментарии 43
Во-первых, ЗАЧЕМ (уже в который раз) давать простейшие вещи, которые и так есть в любой книжке по Linux, в самоучителях, просто понятны из примеров кода, на хабр?
Во-вторых, сами догадаетесь? :)
Во-вторых, сами догадаетесь? :)
-9
Цель — описать понятным и простым языком) В книгах понятного и простого описания я не встретил, к сожалению. Пишу для тех, кто тоже не встретил.
+15
НЛО прилетело и опубликовало эту надпись здесь
Команда find с параметром * выводит в stdout все вложенные папки и файлы, которые находит в данной папке и во всех вложенных.
Неверно. Это сделает команда
find .
Не забываем, что globbing (замена wildcards) происходит в шелле. И
*
по умолчанию не расширяется на dot entries в текущем каталоге.+5
Спасибо. Помогли разобрать разрозненные и сумбурные знания в моей голове :)
+4
Ещё спрашивают «зачем такое постить»…
Столько тонкостей в процессе общественного обсуждения и деления опытом узнаёшь, о которых даже не догадывался.
Аффтар, пиши истчё!!! (простите за эту фразу)
Столько тонкостей в процессе общественного обсуждения и деления опытом узнаёшь, о которых даже не догадывался.
Аффтар, пиши истчё!!! (простите за эту фразу)
+4
За «find *|grep ...» убить готов.
Автор, не пиши больше такое.
Автор, не пиши больше такое.
+9
Это учебный пример, который полностью решает свою задачу: рассказывает о том, как можно управлять потоками. Дальше я оставляю за читателями право посмотреть man'ы всех описанных команд и глубже изучить вопрос.
-1
Лично мне всегда казалось, что примеры должны как _правильно_ использовать приложения, а то, те кто не в теме, увидят find * | grep и будут везде пихать, пока им не откроют глаза на find ./ -name «блабла».
Так что соглашаюсь с предыдущим автором, за find *|grep — надо ругать.
Так что соглашаюсь с предыдущим автором, за find *|grep — надо ругать.
+7
неужели нельзя было придумать примеров получше, чем кривое использование find не по назначению? хотя бы «find /path |grep '/.svn'»
0
Кстати, чтобы не было проблем с
xargs
и другими спецсимволами, лучше всегда пользоваться xargs -d '\n'
. В связке с find
ещё есть find -print0 | xargs -0
+1
Символ перевода строки разрешён в большинстве файловых систем для linux, потому, строго говоря, разделение результатов поиска этим символом чревато. Не думаю, что это имеет большое для практики значение (если, конечно, вы не пишите вдруг CGI-скрипты), но второй способ абсолютно корректен и ничем не хуже первого.
0
НЛО прилетело и опубликовало эту надпись здесь
Обожаю Diablo II =)
0
спасибо за статью, публикуйте и дальше, кому не нужно пусть не читают!
только не забывайте хорошенько все разжевывать :)
вот, например, про xargs узнать бы по подробнее с доходчивыми примерами
только не забывайте хорошенько все разжевывать :)
вот, например, про xargs узнать бы по подробнее с доходчивыми примерами
+2
Нельзя не вспомнить про будильник настоящего юниксоида:
sleep 8h; cat /dev/urandom > /dev/dsp
0
Настоящий юниксоид напишет так:
sleep 8h && cat /dev/urandom > /dev/dsp
sleep 8h && cat /dev/urandom > /dev/dsp
0
Вы удивитесь, но мой код тоже будет работать.
0
Будет (собственно я не говорил, что Ваш код в корне не верен), но настоящий юниксоид напишет:
sleep 8h && cat /dev/urandom > /dev/dsp
Так как код:
sleep 8h; cat /dev/urandom > /dev/dsp
при отсутствии /bin/sleep сразу начнет звенеть…
Ваш пример довольно безобидный, но когда начинают писать
cd /dir1/dir2/dir3; rm *
становится страшно…
sleep 8h && cat /dev/urandom > /dev/dsp
Так как код:
sleep 8h; cat /dev/urandom > /dev/dsp
при отсутствии /bin/sleep сразу начнет звенеть…
Ваш пример довольно безобидный, но когда начинают писать
cd /dir1/dir2/dir3; rm *
становится страшно…
0
Интересно, а как можно разветвить поток (нужно получить из одного потока два, с которыми потом нужно делать разные манипуляции) «стандартным» способом, а то использую для этого awk, как микроскоп для заколачивания гвоздей…
awk '{ print $0 > поток 1; print $0 > поток 2; }'
awk '{ print $0 > поток 1; print $0 > поток 2; }'
+1
man tee
0
Спасибо за совет, но, прочитав мануал, я понял эту команду как:
tee [-ai] [file ...]
The tee utility copies standard input to standard output, making a copy
in zero or more files. The output is unbuffered.
cat ./file.txt | grep 'key' | tee ./file2.txt | grep 'subkey' > ./file3.txt
Как ./file2.txt направить не в физический файл, а в пайп, где я еще хочу сделать sort?
tee [-ai] [file ...]
The tee utility copies standard input to standard output, making a copy
in zero or more files. The output is unbuffered.
cat ./file.txt | grep 'key' | tee ./file2.txt | grep 'subkey' > ./file3.txt
Как ./file2.txt направить не в физический файл, а в пайп, где я еще хочу сделать sort?
0
Спасибо, интересно для новичка
0
У тебя есть такой пример:
Извини, у меня нет цензурных слов. За такое я отрываю разработчикам руки. Такой код в скриптах — это бомба замедленного действия, она срабатывает редко, но неожиданно и разрушительно. О grep-е после find-а и xargs rm вместо -delete уже говорили, но это можно попытаться оправдать тем, что примеры учебные и искуственные. А вот опасность этого примера оправдать нельзя!
Автор, создай у себя, для эксперимента директорию где-нибудь в темпе:
В «документы» положи очень важные и ценные тебе документы. В «документы на удаление» — ерунду. А теперь выполни эту команду и сожалей, что директория «документы» исчезла. Не .svn в этой директории, а «документы» целиком!
Писать так — опасно, учить других писать так — во сто крат опасней! Читать маны перед написанием учебной статьи — напротив, не только неопасно, но и крайне полезно.
find . | grep -e '/.svn$' | xargs rm -Rf
Извини, у меня нет цензурных слов. За такое я отрываю разработчикам руки. Такой код в скриптах — это бомба замедленного действия, она срабатывает редко, но неожиданно и разрушительно. О grep-е после find-а и xargs rm вместо -delete уже говорили, но это можно попытаться оправдать тем, что примеры учебные и искуственные. А вот опасность этого примера оправдать нельзя!
Автор, создай у себя, для эксперимента директорию где-нибудь в темпе:
$ mkdir -p 'документы'/'.svn' 'документы на удаление'/'.svn'
В «документы» положи очень важные и ценные тебе документы. В «документы на удаление» — ерунду. А теперь выполни эту команду и сожалей, что директория «документы» исчезла. Не .svn в этой директории, а «документы» целиком!
Писать так — опасно, учить других писать так — во сто крат опасней! Читать маны перед написанием учебной статьи — напротив, не только неопасно, но и крайне полезно.
+3
Угу, этот пример тоже хорош:
Такой же убийственный
rm -Rf `find . | grep -e '/.svn$'`
Такой же убийственный
0
Спасибо за дельный комментарий.
Но если все таки забыть про учебную составляющую и обратить внимание на саму задачу удаления каталогов .svn, то у меня возник вот какой вопрос: как же правильно написать команду?
У меня не получилось удалить каталоги .svn с использованием -delete, так как я создал там вложенные файлы (это часто бывает в реальной жизни в таком каталоге).
find. -type d -and -iname '.svn' -delete
find: cannot delete `./документы/.svn': Каталог не пуст
В конце концов появился вот такой вариант:
find. -type d -and -iname '.svn' -execdir rm -Rf .svn \; 2>/dev/null
Есть ли более оптимальный?
Но если все таки забыть про учебную составляющую и обратить внимание на саму задачу удаления каталогов .svn, то у меня возник вот какой вопрос: как же правильно написать команду?
У меня не получилось удалить каталоги .svn с использованием -delete, так как я создал там вложенные файлы (это часто бывает в реальной жизни в таком каталоге).
find. -type d -and -iname '.svn' -delete
find: cannot delete `./документы/.svn': Каталог не пуст
В конце концов появился вот такой вариант:
find. -type d -and -iname '.svn' -execdir rm -Rf .svn \; 2>/dev/null
Есть ли более оптимальный?
0
Обычно пользуюсь
Хотя поздновато уже, не ручаюсь.
find -print0 | xargs -0
. А только средствами find… попробуйтеfind . -depth \( -path '*/.svn/*' -or -iname '.svn' \) -delete
Хотя поздновато уже, не ручаюсь.
0
find ищет по каким-то условиям и выполняет определённое действие с результатом поиска. Дело в том, что по умолчанию find делает -print, то есть выводит результат на стандартный вывод, разделяя имена переводом строки.
xargs читает со стандартного ввода записи, разделяя, их, среди прочего, и пробелами. Таким образом, если find найдёт файл с именем «раз два», то xargs запустит указанную команду с аргументами «раз» и «два». Нам нужно, чтобы find разделял записи разделителем, который не может присутствовать в именах файлов. Среди ext2/3 таких символов два — это нулевой символ (не имеет печатаемого обозначения) и символ прямого слэша. Прямой слэш, кажется, в некоторых файловых системах может являться частью имени файла, потому нам остаётся только нулевой символ.
Как сказано в мануале в первых строках по find: «you should probably consider using ‘-print0’ instead».
Действие -print0 заставляет find вывести на стандартный вывод результаты, разделяемые нулевым символом, а опция -0 у xargs заставляет в качестве разделителя записей принимать только нулевой символ.
В моём мане (это не сарказм, маны на разных системах бывают очень разные) есть такой пример для этого дела:
Что касается возможности запуска без xargs — для скриптов я бы посоветовал такую конструкцию:
Для применения вручную, после запуска без -delete и изучения списка:
При этом, файлы и директории типа .svnlalala тоже будут уничтожены, если присутствуют.
xargs читает со стандартного ввода записи, разделяя, их, среди прочего, и пробелами. Таким образом, если find найдёт файл с именем «раз два», то xargs запустит указанную команду с аргументами «раз» и «два». Нам нужно, чтобы find разделял записи разделителем, который не может присутствовать в именах файлов. Среди ext2/3 таких символов два — это нулевой символ (не имеет печатаемого обозначения) и символ прямого слэша. Прямой слэш, кажется, в некоторых файловых системах может являться частью имени файла, потому нам остаётся только нулевой символ.
Как сказано в мануале в первых строках по find: «you should probably consider using ‘-print0’ instead».
Действие -print0 заставляет find вывести на стандартный вывод результаты, разделяемые нулевым символом, а опция -0 у xargs заставляет в качестве разделителя записей принимать только нулевой символ.
В моём мане (это не сарказм, маны на разных системах бывают очень разные) есть такой пример для этого дела:
find /tmp -name core -type f -print0 | xargs -0 /bin/rm -f
Что касается возможности запуска без xargs — для скриптов я бы посоветовал такую конструкцию:
find -depth \( -type f -a -wholename '*/.svn/*' \) -delete -o \( -type d -a -name '.svn' \) -delete
Для применения вручную, после запуска без -delete и изучения списка:
find -depth -wholename '*/.svn*' -delete
При этом, файлы и директории типа .svnlalala тоже будут уничтожены, если присутствуют.
+3
мощнейшая штука потоки, вот только если в умелых руках… замена ">" на "
0
> rm -Rf `find. | grep -e '/.svn$'`
Мда…
Как насчет man find в районе exec?
Просто любопытно: вы программы как устанавливаете? ./configure; make; make install?
Мда…
Как насчет man find в районе exec?
Просто любопытно: вы программы как устанавливаете? ./configure; make; make install?
-1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Потоки данных