Использовать
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.