Вопрос

Я не совсем понимаю пример, приведенный из man find, может ли кто -нибудь привести мне несколько примеров и объяснений? Могу ли я объединить в нем регулярное выражение?


Более подробный вопрос такой:

Напишите сценарий оболочки, changeall, который имеет интерфейс, как changeall [-r|-R] "string1" "string2". Анкет Он найдет все файлы с суффиксом .h, .C, .cc, или же .cpp и изменить все входы string1 к string2. -r вариант для пребывания только в текущем DIR или включая Subdir's.

ПРИМЕЧАНИЕ:

  1. Для нерекурсивного случая, ls не допускается, мы могли только использовать find а также sed.
  2. Я старался find -depth Но это не было поддержано. Вот почему мне было интересно, если -prune мог помочь, но не понял примера из man find.

Edit2: Я выполнял задание, я не задавал вопроса в отличных деталях, потому что я хотел бы закончить его сам. Так как я уже сделал это и передал это, теперь я могу указать весь вопрос. Кроме того, мне удалось закончить задание без использования -prune, но все равно хотел бы узнать это.

Это было полезно?

Решение

То, что я нашел с толку, о -prune это действие (например -print), а не тест (как -name) Он изменяет список «дел», но всегда возвращается правдой.

Общий шаблон для использования -prune это:

find [path] [conditions to prune] -prune -o \
            [your usual conditions] [actions to perform]

Вы в значительной степени всегда хотите -o (логично или) сразу после -prune, потому что эта первая часть теста (вплоть до и включать -prune) вернется ЛОЖЬ за то, что вы действительно хотите (т.е. то, что вы не хочу обрезать).

Вот пример:

find . -name .snapshot -prune -o -name '*.foo' -print

Это найдет файлы «*.foo», которые не находятся под ».snapshot». В этом примере, -name .snapshot составляет [conditions to prune], а также -name '*.foo' -print является [your usual conditions] а также [actions to perform].

Важные заметки:

  1. Если все, что вы хотите сделать, это напечатать результаты, которые вы можете привыкнуть к выпуску -print действие. Ты вообще не хочу сделать это при использовании -prune.

    Поведение находка по умолчанию - и " весь выражение с -print действие, если нет никаких действий, кроме как -prune (по иронии судьбы) в конце. Это означает, что написание этого:

    find . -name .snapshot -prune -o -name '*.foo'              # DON'T DO THIS
    

    эквивалентно написанию этого:

    find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS
    

    Это означает, что он также распечатает имя каталога, который вы обрезаете, что обычно не то, что вы хотите. Вместо этого лучше явно указать -print Действие, если это то, что вы хотите:

    find . -name .snapshot -prune -o -name '*.foo' -print       # DO THIS
    
  2. Если ваше «обычное условие» соответствует файлам, которые также соответствуют условию вашей черносливы, эти файлы будут нет быть включенным в выход. Способ исправить это - добавить -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).

Другие советы

Остерегайтесь того, что -prune не мешает спуститься в Любые каталог, как говорили некоторые. Он предотвращает спуск в каталоги, которые соответствуют тесту, к которому он применяется. Возможно, некоторые примеры помогут (см. Внизу для примера корпорации). Извините за то, что это было таким длинным.

$ 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 и понимаете, что получаете слишком много файлов из каталогов, которые вы хотите не делать. Давайте исключаем /СМИ, чтобы избежать поиска ваших монтированных дисков.
Теперь вы должны просто добавить следующее к предыдущей команде:

-print -o -path '/media' -prune

Итак, окончательная команда:

find / -name "*.php" -print -o -path '/media' -prune

............... | <--- Включить ---> | .................... | <- -------- Исключить ---------> |

Я думаю, что эта структура намного проще и коррелирует с правильным подходом

Добавление к совету, приведенным в других ответах (у меня нет представителя создавать ответы) ...

При комбинировании -prune С другими выражениями существует тонкая разница в поведении в зависимости от того, какие другие выражения используются.

Пример @laurence Gonsalves найдет файлы «*.foo», которые не находятся под ».snapshot»:-

find . -name .snapshot -prune -o -name '*.foo' -print

Тем не менее, эта немного другая короткая рука, возможно, непреднамеренно, также перечисляет .snapshot каталог (и любые вложенные каталоги .snapshot):-

find . -name .snapshot -prune -o -name '*.foo'

Причина в том, что (согласно данной странице в моей системе):-

Если данное выражение не содержит ни одного из первичных -эксек, -ls, -ok или -print, данное выражение эффективно заменяется:

(dead_expression) -print

То есть второй пример- это эквивалент ввода следующего, тем самым изменяя группировку терминов:-

find . \( -name .snapshot -prune -o -name '*.foo' \) -print

Это, по крайней мере, было замечено на Solaris 5.10. Используя различные ароматы *NIX в течение примерно 10 лет, я только недавно искал причину, почему это происходит.

Чублок - это не повторять ни на одном переключателе каталогов.

Со страницы человека

Если -depth не дается, правда; Если файл является каталогом, не спускайтесь в него. Если -депт дан, ложь; нет эффекта.

В основном это не останется в каких -либо суб -каталогах.

Возьмите этот пример:

У вас есть следующие каталоги

  • /home/test2
  • /home/test2/test2

Если вы бежите find -name test2:

Он вернет оба каталога

Если вы бежите find -name test2 -prune:

Он вернется только/home/test2, так как он не спускается в/home/test2, чтобы найти/home/test2/test2

I am no expert at this (and this page was very helpful along with http://mywiki.wooledge.org/UsingFind)

Just noticed -path is for a path that fully matches the string/path that comes just after find (. in theses examples) where as -name matches all basenames.

find . -path ./.git  -prune -o -name file  -print

blocks the .git directory in your current directory ( as your finding in . )

find . -name .git  -prune -o -name file  -print

blocks all .git subdirectories recursively.

Note the ./ is extremely important!! -path must match a path anchored to . or whatever comes just after find if you get matches with out it (from the other side of the or '-o') there probably not being pruned! I was naively unaware of this and it put me of using -path when it is great when you don't want to prune all subdirectory with the same basename :D

Show everything including dir itself but not its long boring contents:

find . -print -name dir -prune

If you read all the good answers here my understanding now is that the following all return the same results:

find . -path ./dir1\*  -prune -o -print

find . -path ./dir1  -prune -o -print

find . -path ./dir1\*  -o -print
#look no prune at all!

But the last one will take a lot longer as it still searches out everything in dir1. I guess the real question is how to -or out unwanted results without actually searching them.

So I guess prune means don't decent past matches but mark it as done...

http://www.gnu.org/software/findutils/manual/html_mono/find.html "This however is not due to the effect of the ‘-prune’ action (which only prevents further descent, it doesn't make sure we ignore that item). Instead, this effect is due to the use of ‘-o’. Since the left hand side of the “or” condition has succeeded for ./src/emacs, it is not necessary to evaluate the right-hand-side (‘-print’) at all for this particular file."

find builds a list of files. It applies the predicate you supplied to each one and returns those that pass.

This idea that -prune means exclude from results was really confusing for me. You can exclude a file without prune:

find -name 'bad_guy' -o -name 'good_guy' -print  // good_guy

All -prune does is alter the behavior of the search. If the current match is a directory, it says "hey find, that file you just matched, dont descend into it". It just removes that tree (but not the file itself) from the list of files to search.

It should be named -dont-descend.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top