Виключіть підкаталог, використовуючи find


115

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

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

У всіх папках всередині каталогу даних є вхідна підпапка. Я хочу отримати всі файли з усіх папок і підпапок, за винятком режимів def / incoming та 456 / вхідних. Я спробував виконати наступну команду

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

але це працює не так, як очікувалося.

Раві


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

Чи відповідає це на ваше запитання? Як виключити каталог у пошуку. команда
imz - Іван Захарящев

Відповіді:


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як частину його шляху

помилка "знайти: погана опція - не знайти: список предикатів-список предикатів"
Раві

@Ravi ти використовуєш bash shell? Я щойно тестував це на своєму терміналі, і це працює на мене. Спробуйте скопіювати та вставити рішення замість цього, якщо ви внесли зміни до свого сценарію.
Сампсон-Чень

Він працює, але його перелік діріс не зберігає файлів у цих дірах.
Раві

1
-pathвідповідає цілому рядку, тож якщо ти робиш find ., то твої -pathструни повинні бути./path/to/directory/*
Heath Borders

1
FYI, -not -pathбезумовно, буде працювати в цьому прикладі, але findвсе ще перебирається в структуру каталогів і використовує цикли процесорів, щоб переглядати всі ці каталоги / файли. щоб запобігти findітерації над цими каталогами / файлами (можливо, там є мільйони файлів), тоді вам потрібно скористатися -prune( -pruneоднак цей варіант важко використовувати).
Тревор Бойд Сміт

9

Тільки заради документації: Можливо, вам доведеться копати глибше, оскільки є багато сузір’їв пошуку (як і я). Може виявитись, що 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
фіс.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.