Як виключити / проігнорувати приховані файли та каталоги у вбудованому для підкреслення пошуку «знайти»?


119

Починаючи з (помічайте підстановку перед і після "деякого тексту")

find . -type f -name '*some text*'

як можна виключити / ігнорувати всі приховані файли та каталоги?

Я вже занадто довго гуляв, натрапив на -берез і! (знаки оклику) параметри, але жодного примірного (та парсимонічного) прикладу, який щойно працював .

Трубопровід | - grepце варіант, і я також вітаю приклади цього; але в першу чергу мене цікавить короткий однолінійний (або кілька автономних однолінійних, які ілюструють різні способи досягнення однієї і тієї самої мети командного рядка) просто за допомогою find.

ps: Пошук файлів у Linux та виключення конкретних каталогів здається тісно пов’язаним, але а) ще не прийнято, і b) пов'язане, але відрізняється і відрізняється, але c) може надати натхнення та допомогти визначити плутанину!

Редагувати

find . \( ! -regex '.*/\..*' \) -type f -name "whatever", працює. Регекс шукає "що завгодно, потім косу рису, точку, потім все" (тобто всі приховані файли та папки, включаючи їх підпапки), і "!" заперечує регулярний вираз.


Не допомагає те, що ви задали у своїй редакції, але подивіться на моє запитання та його відповідь тут: unix.stackexchange.com/q/69164/15760, а також посилання у відповіді.

Відповіді:


134

Це друкує всі файли, які є нащадками вашого каталогу, пропускаючи приховані файли та каталоги:

find . -not -path '*/\.*'

Отже, якщо ви шукаєте файл із some textйого ім'ям, і хочете пропустити приховані файли та каталоги, запустіть:

find . -not -path '*/\.*' -type f -name '*some text*'

Пояснення:

-pathОпція запускає перевіряє зразок проти всього рядка шляху. *є символом підстановки, /є роздільником каталогів, \.є крапкою (її потрібно уникати, щоб уникнути особливого значення), і *є іншим символом. -notозначає не вибирати файли, які відповідають цьому тесту.

Я не думаю, що findце досить розумно, щоб уникнути рекурсивного пошуку прихованих каталогів у попередній команді, тому, якщо вам потрібна швидкість, використовуйте -pruneзамість цього:

 find . -type d -path '*/\.*' -prune -o -not -name '.*' -type f -name '*some text*' -print

Зверніть увагу на останньому, що вам потрібно -printв кінці! Крім того, не впевнений, чи -name '\.*' would be more efficient instead of шлях-так "(тому що шлях шукає піддоріжки, але вони будуть викреслені)
artfulrobot

У чому особливий сенс .цього контексту?
frostschutz

@frostschutz Точка після findозначає поточний каталог: findперегляне всі файли та каталоги в поточному каталозі. Аргумент після path- це регулярний вираз, де крапка зазвичай означає "будь-який символ", щоб це означало буквальну крапку, ми повинні уникати її з косою рисою. Аргумент після -name - це не регулярний вираз, але він розширює символи, як ?і *як оболонка.
Флейм

2
@frostschutz Насправді, подумайте про це, я, можливо, помиляюся .з особливим значенням.
Flimm

1
@Flimm yup, не потрібно бігти .. Наскільки мені відомо, потрібно тільки їх екранувати: *, ?і [].
1717 року

10

Це один з небагатьох засобів виключення точкових файлів, який також правильно працює на BSD, Mac та Linux:

find "$PWD" -name ".*" -prune -o -print
  • $PWD вивести повний шлях до поточного каталогу, щоб шлях не починався з ./
  • -name ".*" -prune відповідає будь-яким файлам чи каталогів, які починаються з крапки, а потім не спускаються
  • -o -printозначає надрукувати ім’я файлу, якщо попередній вираз нічого не відповідав. Використання -printабо -print0спричинення, що всі інші вирази не друкуються за замовчуванням.

Будь ласка, поясніть / докладіть "тривожно складне"; відповіді вже дані, а ваша відповідь, здається, свідчить про протилежне ...?
горіх про natty

2
"тривожно складний", ймовірно, надмірний. Я переформулював відповідь, щоб перейти до справи. Я думаю, що відповідь, яку я опублікував, важко зрозуміти і її важко зрозуміти без дуже уважного прочитання сторінки людини. Якщо ви використовуєте лише GNU find, тоді є більше можливих рішень.
ерадман

-o ... -printкорисно. Для мого використання зараз я маю find ... '!' -name . -name '.*' -prune -o ... -print, що було зручніше, ніж включати $ PWD.
Roger Pate

4
find $DIR -not -path '*/\.*' -type f \( ! -iname ".*" \)

Виключає всі приховані каталоги та приховані файли під $ DIR


Це ідеальна відповідь. Він рекурсивно знаходить усі файли, але виключає позиції для каталогів та прихованих файлів. Дякую!
KyleFarris

2

Відповідь я спочатку розміщений як «редагувати» на мій первісний питання вище:

find . \( ! -regex '.*/\..*' \) -type f -name "whatever", працює. Регекс шукає "що завгодно, потім косу рису, точку, потім все" (тобто всі приховані файли та папки, включаючи їх підпапки), і "!" заперечує регулярний вираз.


Схожий, але лише для поточної папки:find . \( ! -regex './\..*' \) -type f -maxdepth 1 -print
фіат

2

Не потрібно використовувати findдля цього. Просто використовуйте globstar в оболонці, як:

echo **/*foo*

або:

ls **/*foo*

де **/представлена ​​будь-яка папка рекурсивно та *foo*будь-який файл, що має fooсвоє ім'я.

За замовчуванням за допомогою lsдрукуються імена файлів, за винятком прихованих файлів та каталогів.

Якщо у вас не включений глобус, зробіть це shopt -s globstar.

Примітка . Нова опція глобалізації працює в Bash 4, zsh та подібних оболонках.


Приклад:

$ mkdir -vp a/b/c/d
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
mkdir: created directory 'a/b/c/d'
$ touch a/b/c/d/foo a/b/c/d/bar  a/b/c/d/.foo_hidden a/b/c/d/foo_not_hidden
$ echo **/*foo*
a/b/c/d/foo  a/b/c/d/foo_not_hidden

5
Вам цього не потрібно ls! echo **/*foo*
Кевін Кокс

@kenorb (і @ kevin-cox). Чи можете ви бути трохи більш багатослівним? Чому glostarstar (= *) працює тут і як? Що означає косою рискою?
горіх про natty

@nuttyaboutnatty /означає папку, вона відокремлює каталоги від імені файлу. *в основному представляє все.
kenorb

@kenorb так-але: як це однолінійка допомагає в оригінальному запитанні?
горіх про natty

1
@nuttyaboutnatty Уточнено та додано приклад. Це допомагає, знаходячи файли, ігноруючи прихований.
kenorb

1

@ Флімм в відповідь хороший, особливо тому , що він НЕ дозволяє знайти від сповзання в приховані каталоги . Я віддаю перевагу цьому спрощенню:

Як правило, щоб виключити всі приховані шляхи (звичайні файли, каталоги тощо):

find <start-point> -path '*/.*' -prune -o <expression> -print

Наприклад, використовуючи робочий каталог як початкову точку, і -name '*some text*'як вираз:

find . -path '*/.*' -prune -o -name '*some text*' -print

На відміну від того, що пропонує відповідь @ Flimm, відсутність прихованих файлів чи прихованих каталогів є простим випадком. -path '*/.*'Вираз вірно для будь-якого шляху (звичайні файли, каталоги і т.д.) , який має .відразу після роздільник файлів, /. Таким чином, цей рядок буде обрізати і приховані файли, і каталоги.

Дозволити приховані файли, виключаючи приховані каталоги - це випадок, який потребує подальшого фільтрування. Тут ви б включили -type dу вираз, що обрізається.

find <start-point> -type d -path '*/.*' -prune -o <expression> -print 

Наприклад:

find . -type d -path '*/.*' -prune -o -name '*some text*' -print

В цьому випадку -type d -path '*/.*'є trueтільки для каталогів, і тому тільки каталоги обрізають.


0

findмає чіткі логічні перемикачі, такі як, -andі -notви можете використовувати їх на вашу користь, щоб знайти файл, що відповідає, з двома правилами:

$ touch non_hidden_file.txt .hidden_file.txt somethings/.another_hidden_file.txt                                                 

$ find . -type f -name '*hidden_file*' -and \( -not -name ".*" \)                            
./non_hidden_file.txt

Як бачите, findвикористовуйте два правила -name '*hidden_file*'та -and \( -not -name ".*" \)знаходьте ті імена файлів, які відповідають обом умовам - ім'я файлу hidden_fileв ньому, але без ведучої крапки. Зверніть увагу на косої риски перед круглими дужками - вони використовуються для визначення круглих дужок як findаргументів, а не для визначення нижньої частини оболонки.


0
$ pwd
/home/victoria

$ find $(pwd) -maxdepth 1 -type f -not -path '*/\.*' | sort
/home/victoria/new
/home/victoria/new1
/home/victoria/new2
/home/victoria/new3
/home/victoria/new3.md
/home/victoria/new.md
/home/victoria/package.json
/home/victoria/Untitled Document 1
/home/victoria/Untitled Document 2

$ find . -maxdepth 1 -type f -not -path '*/\.*' | sed 's/^\.\///g' | sort
new
new1
new2
new3
new3.md
new.md
package.json
Untitled Document 1
Untitled Document 2

Примітки:

  • . : поточна папка
  • видалити -maxdepth 1для пошуку рекурсивно
  • -type f: знайти файли, а не каталоги ( d)
  • -not -path '*/\.*' : не повертаються .hidden_files
  • sed 's/^\.\///g': видаліть попередньо ./зі списку результатів
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.