Как использовать опцию «--
Вопрос
Я не совсем понимаю пример, приведенный из man find
, может ли кто -нибудь привести мне несколько примеров и объяснений? Могу ли я объединить в нем регулярное выражение?
Более подробный вопрос такой:
Напишите сценарий оболочки, changeall
, который имеет интерфейс, как changeall [-r|-R] "string1" "string2"
. Анкет Он найдет все файлы с суффиксом .h
, .C
, .cc
, или же .cpp
и изменить все входы string1
к string2
. -r
вариант для пребывания только в текущем DIR или включая Subdir's.
ПРИМЕЧАНИЕ:
- Для нерекурсивного случая,
ls
не допускается, мы могли только использоватьfind
а такжеsed
. - Я старался
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]
.
Важные заметки:
Если все, что вы хотите сделать, это напечатать результаты, которые вы можете привыкнуть к выпуску
-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
Если ваше «обычное условие» соответствует файлам, которые также соответствуют условию вашей черносливы, эти файлы будут нет быть включенным в выход. Способ исправить это - добавить
-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
.