Исключить подкаталог с помощью find


115

У меня такая структура каталогов

data
|___
   |
   abc
    |____incoming
   def
    |____incoming
    |____processed
   123
    |___incoming
   456
    |___incoming
    |___processed

Во всех папках внутри каталога данных есть входящая подпапка. Я хочу получить все файлы из всех папок и подпапок, кроме каталогов def / incoming и 456 / incoming. Я попробовал следующую команду

 find /home/feeds/data -type d \( -name 'def/incoming' -o -name '456/incoming' -o -name arkona \) -prune -o -name '*.*' -print

но он работает не так, как ожидалось.

Ravi


3
Это не очень хороший совет, но он быстро и грязно вытащит вас из многих ситуаций: выделите его, grep -v somethingчтобы исключить все, что вам не нужно
Miquel

Ответы:


206

Это работает:

find /home/feeds/data -type f -not -path "*def/incoming*" -not -path "*456/incoming*"

Объяснение:

  • find /home/feeds/data: начать поиск рекурсивно с указанного пути
  • -type f: найти только файлы
  • -not -path "*def/incoming*": не включать ничего с def/incomingкак часть своего пути
  • -not -path "*456/incoming*": не включать ничего с 456/incomingкак часть своего пути

получение ошибки «find: bad option -not find: path-list predicate-list»
Рави,

@Ravi, вы используете оболочку bash? Я только что протестировал это на своем терминале, и у меня это работает. Попробуйте скопировать и вставить решение, если вы внесли изменения в свой сценарий.
sampson-chen

Он работает, но он перечисляет каталоги, а не файлы в этих каталогах.
Ravi

1
-pathсоответствует всей строке, так что, если вы это делаете find ., ваши -pathстроки должны быть./path/to/directory/*
Heath Borders

1
FYI -not -pathопределенно будет работать в этом примере, но findвсе еще перебирает структуру каталогов и использует циклы процессора для перебора всех этих каталогов / файлов. чтобы предотвратить findитерацию по этим каталогам / файлам (возможно, там миллионы файлов), вам нужно использовать -prune( -pruneоднако этот параметр сложно использовать).
Trevor Boyd Smith

9

Просто для документации: вам, возможно, придется копнуть глубже, поскольку существует множество созвездий search'n'skip (как и мне). Может оказаться, что pruneваш друг -not -pathне сделает того, чего вы ожидаете.

Итак, это ценный пример из 15 примеров поиска, исключающих каталоги:

http://www.theunixschool.com/2012/07/find-command-15-examples-to-exclude.html

Чтобы связать с исходным вопросом, исключение, наконец, сработало для меня следующим образом:

find . -regex-type posix-extended -regex ".*def/incoming.*|.*456/incoming.*" -prune -o -print 

Затем, если вы хотите найти один файл и по-прежнему исключить пути, просто добавьте | grep myFile.txt.

Это также может зависеть от вашей версии поиска. Я вижу:

$ find -version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX

5

-nameсоответствует только имени файла, а не всему пути. -pathВместо этого вы хотите использовать для частей, в которых вы сокращаете каталоги, например def/incoming.


2
find $(INP_PATH} -type f -ls |grep -v "${INP_PATH}/.*/"

7
Некоторые объяснения могут сделать это гораздо лучшим ответом.
Крис Луенго

Спасибо за этот фрагмент кода, который может предоставить некоторую краткосрочную помощь. Правильное объяснение значительно повысило бы его ценность в долгосрочной перспективе, показав, почему это хорошее решение проблемы, и сделало бы его более полезным для будущих читателей с другими подобными вопросами. Пожалуйста, отредактируйте свой ответ, чтобы добавить некоторые пояснения, в том числе сделанные вами предположения
Шон С.

1
Примечание: этот трюк не работает, если использовать его find ... -print0вместе с более позднимxargs -0
phs

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.