Використовуйте
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
повертає true і є каталогом, поверніть true для цього каталогу і не спускайтеся в нього.
-path "./script" ! -prune
- це оцінює як (-path "./script") AND (! -prune)
. Це повертає "завжди істинну" чорносливу до завжди помилкової. Це дозволяє уникнути друку "./script"
як сірника.
-path "./script" -prune -false
- оскільки -prune
завжди повертає true, ви можете слідувати за ним, -false
щоб зробити те саме, що !
.
-o
- АБО оператор. Якщо між двома виразами не вказано жодного оператора, то за замовчуванням використовується оператор І.
Отже, \( -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
.