Использовать
find \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
или
find \( -path "./tmp" -o -path "./scripts" \) -prune -false -o -name "*_peaks.bed"
или
find \( -path "./tmp" -path "./scripts" \) ! -prune -o -name "*_peaks.bed"
Порядок важен. Он оценивается слева направо. Всегда начинайте с исключения пути.
Объяснение
Не используйте -not
(или !
) для исключения всего каталога. Используйте -prune
. Как объяснено в руководстве:
−prune The primary shall always evaluate as true; it
shall cause find not to descend the current
pathname if it is a directory. If the −depth
primary is specified, the −prune primary shall
have no effect.
и в руководстве по поиску GNU:
-path pattern
[...]
To ignore a whole
directory tree, use -prune rather than checking
every file in the tree.
Действительно, если вы используете -not -path "./pathname"
, find будет оценивать выражение для каждого узла ниже "./pathname"
.
Выражения find - это просто оценка условий.
\( \)
- групповая работа (можно использовать -path "./tmp" -prune -o -path "./scripts" -prune -o
, но более многословно).
-path "./script" -prune
- если -path
возвращает истину и является каталогом, вернуть истину для этого каталога и не спускаться в него.
-path "./script" ! -prune
- оценивается как (-path "./script") AND (! -prune)
. Он меняет «всегда верно» для слова «всегда ложно». Это позволяет избежать печати "./script"
совпадений.
-path "./script" -prune -false
- поскольку -prune
всегда возвращает истину, вы можете следовать за ним, -false
чтобы сделать то же самое, чем !
.
-o
- Оператор ИЛИ. Если между двумя выражениями не указан оператор, по умолчанию используется оператор AND.
Следовательно, \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
расширяется до:
[ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )
Печать здесь важна, потому что без нее расширяется до:
{ [ (-path "./tmp" OR -path "./script" ) AND -prune ] OR (-name "*_peaks.bed" ) } AND print
-print
добавляется с помощью find - поэтому в большинстве случаев вам не нужно добавлять его в выражение. А поскольку -prune
вернет true, он напечатает «./script» и «./tmp».
В других это не обязательно, потому что мы переключились -prune
на всегда возвращать false.
Подсказка: вы можете использовать, find -D opt expr 2>&1 1>/dev/null
чтобы увидеть, как он оптимизирован и расширен,
find -D search expr 2>&1 1>/dev/null
чтобы увидеть, какой путь отмечен.
_peaks.bed
.