Как использовать опцию' - prune ' из 'find' в sh?
Я не совсем понимаю пример, приведенный из "man find", может ли кто-нибудь дать мне некоторые примеры и объяснения? Могу ли я объединить регулярное выражение в нем?
более подробный вопрос выглядит так: напишите сценарий оболочки, changeall, который имеет интерфейс типа "changeall [-r|-R] "string1" "string2". Он найдет все файлы с суффиксом .ч. ,С, .CC или .cpp и измените все вхождения " string1 "на"string2". - r-это вариант для пребывания только в текущем dir Примечание: 1) для нерекурсивного случая " ls "не допускается, мы могли бы использовать только "find" и "sed". 2) я попытался "найти глубину", но это не было поддержано. Вот почему мне было интересно, может ли "- prune "помочь, но не понял пример из "man find".
EDIT2: я делал задание, я не задавал вопрос в деталях, потому что я хотел бы закончить его сам. Поскольку я уже сделал это и сдал его, теперь я могу сформулировать весь вопрос. Кроме того, мне удалось чтобы закончить задание без чернослива, но хотелось бы все равно узнать его.
8 ответов:
то, что я нашел запутанным о о
-pruneзаключается в том, что это действие (например,-name). Он изменяет список "дел",но всегда возвращает true.общий шаблон для использования
-pruneэто:find [path] [conditions to prune] -prune -o \ [your usual conditions] [actions to perform]вы в значительной степени всегда хотите the
-oсразу после-prune, потому что это первая часть теста (до включения-prune) возвращает ложные для чего вы на самом деле хотите (т. е.: то, что вы не хотите обрезать).вот пример:
find . -name .snapshot -prune -o -name '*.foo' -printэто найдет "*.ФОО" файлы, которые не находятся под ".моментальный снимок" каталоги. В этом примере
-name .snapshotэто "тесты на материал, который вы хотите обрезать", и-name '*.foo' -printэто "материал, который вы обычно ставите после пути".важная информация:
если все вы хотите сделать, это распечатать результаты можно было выходить элемент
-prune.поведение по умолчанию find является "и"весь выражение
-prune(иронично) в конце. Это означает, что написание этого:find . -name .snapshot -prune -o -name '*.foo' # DON'T DO THISэквивалентно написанию этого:
find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THISэто означает, что он также распечатает имя каталога, который вы обрезаете, что обычно, не то, что вы хотите. Вместо этого лучше явно указать
find . -name .snapshot -prune -o -name '*.foo' -print # DO THISесли ваше" обычное состояние " совпадает с файлами, которые также соответствуют вашему состоянию чернослива, эти файлы будут не быть включены в выходные данные. Способ исправить это-добавить
-type dпредикат для вашего состояния чернослива.например, предположим, что мы хотели вырезать любой каталог, который начинался с
.git(это, по общему признанию, несколько надуманно - обычно вам нужно только удалить вещь с именем ровно.git), но кроме этого хотел видеть все файлы, в том числе такие файлы, как.gitignore. Вы можете попробовать это:find . -name '.git*' -prune -o -type f -print # DON'T DO THISэто не включить
.gitignoreна выходе. Вот исправленная версия:find . -type d -name '.git*' -prune -o -type f -print # DO THISдополнительный совет: если вы используете версию GNU
find, страница texinfo дляfindподробнее подробное объяснение, чем его manpage (как это верно для большинства утилит GNU).
будьте осторожны-чернослив не мешает спускаться в любой каталог, как некоторые сказали. Он предотвращает спуск в каталоги, соответствующие тесту, к которому он применяется. Возможно, некоторые примеры помогут (см. Внизу пример регулярного выражения). К сожалению для этого быть таким длительным.
$ find . -printf "%y %p\n" # print the file type the first time FYI d . f ./test d ./dir1 d ./dir1/test f ./dir1/test/file f ./dir1/test/test d ./dir1/scripts f ./dir1/scripts/myscript.pl f ./dir1/scripts/myscript.sh f ./dir1/scripts/myscript.py d ./dir2 d ./dir2/test f ./dir2/test/file f ./dir2/test/myscript.pl f ./dir2/test/myscript.sh $ find . -name test ./test ./dir1/test ./dir1/test/test ./dir2/test $ find . -prune . $ find . -name test -prune ./test ./dir1/test ./dir2/test $ find . -name test -prune -o -print . ./dir1 ./dir1/scripts ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.sh ./dir1/scripts/myscript.py ./dir2 $ find . -regex ".*/my.*p.$" ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.py ./dir2/test/myscript.pl $ find . -name test -prune -regex ".*/my.*p.$" (no results) $ find . -name test -prune -o -regex ".*/my.*p.$" ./test ./dir1/test ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.py ./dir2/test $ find . -regex ".*/my.*p.$" -a -not -regex ".*test.*" ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.py $ find . -not -regex ".*test.*" . ./dir1 ./dir1/scripts ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.sh ./dir1/scripts/myscript.py ./dir2
обычно родной способ мы делаем вещи в linux и то, как мы думаем, слева направо.
Так что вы бы пойти и написать то, что вы ищете в первую очередь:find / -name "*.php"тогда вы, вероятно, нажмете enter и поймете, что получаете слишком много файлов из каталоги, которые вы не хотите. Давайте исключим /media, чтобы избежать поиска подключенных дисков.
Теперь вы должны просто добавить следующее к предыдущей команде:-print -o -path '/media' -pruneИтак, последняя команда это:
find / -name "*.php" -print -o -path '/media' -prune...............|--- ...................||
Я думаю, что эта структура намного проще и коррелирует с правильным подходом
добавление к советам, приведенным в других ответах (у меня нет репутации для создания ответов)...
при объединении
-pruneС другими выражениями существует тонкая разница в поведении в зависимости от того, какие другие выражения используются.@Laurence Gonsalves' пример найдет "*.ФОО" файлы, которые не находятся под ".снимок" каталоги:-
find . -name .snapshot -prune -o -name '*.foo' -printоднако эта немного другая короткая рука будет, возможно, непреднамеренно, также перечислять
Prune-это не рекурсия в любом коммутаторе каталогов.
из man-страницы
Если-глубина не задана, true; если файл является каталогом, не спускайтесь в него. Если-глубина задана, ложь; никакого эффекта.
в основном он не будет десенд в любые подкаталоги.
рассмотрим пример:
у вас есть следующие каталоги
- / home / test2
- в/Home/test2 на/условие_2
Если вы запустите
find -name test2:он вернет оба каталога
Если вы запустите
find -name test2 -prune:он вернется только /home / test2, поскольку он не будет спускаться в /home /test2, чтобы найти/home/test2 / test2
Я не эксперт в этом (и эта страница была очень полезна вместе с http://mywiki.wooledge.org/UsingFind)
только что заметил
-pathна пути полностью соответствует строке / пути, который приходит сразу послеfind(.в этих примерах) где как-nameсоответствует всем имена.find . -path ./.git -prune -o -name file -printблокирует .каталог git в вашем текущем каталоге ( как ваша находка в
.)find . -name .git -prune -o -name file -printблокирует все .ГИТ поддиректории рекурсивно.
Примечание
./очень важно!!-pathдолжен соответствовать пути, привязанному к.или все, что приходит сразу после найти если вы получаете спички с ним (с другой стороны или'-o') там, вероятно, не обрезается! Я наивно не знал об этом, и это поставило меня в using-path, когда это здорово, когда вы не хотите обрезать все подкаталоги с помощью то же самое базовое имя :D
Если Вы читаете все хорошие ответы здесь, я понимаю, что следующие все возвращают те же результаты:
find . -path ./dir1\* -prune -o -print find . -path ./dir1 -prune -o -print find . -path ./dir1\* -o -print #look no prune at all!но последний займет намного больше времени, поскольку он все еще ищет все в dir1. Я думаю, реальный вопрос заключается в том, как
-orиз нежелательных результатов без фактического поиска их.поэтому я думаю, что чернослив означает, что не приличные прошлые матчи, но отметьте его как сделанный...
http://www.gnu.org/software/findutils/manual/html_mono/find.html "Это, однако, не связано с эффектом действия "- prune " (который только предотвращает дальнейшее снижение, он не гарантирует, что мы игнорируем этот элемент). Вместо этого этот эффект обусловлен использованием ‘-o’. Так как левая сторона условия " или "преуспела./src / emacs, нет необходимости оценивать правую сторону (’- print') вообще для этого конкретного файла."
Comments