Как исключить / игнорировать скрытые файлы и каталоги при поиске с использованием подстановочного знака «поиск»?


119

Начиная с (обратите внимание на подстановочные знаки до и после «некоторого текста»)

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

Как можно исключить / игнорировать все скрытые файлы и каталоги?

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

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

PS: Найти файлы в Linux и исключить конкретные каталоги, кажется, тесно связаны, но а) еще не принято и б) связано, но отличается и отличается, но в) может дать вдохновение и помочь выявить путаницу!

редактировать

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 -path` (потому что путь ищет подпути, но они будут
удалены

Каково особое значение .в этом контексте?
frostschutz

@frostschutz Точка после findозначает текущий каталог: findбудет искать все файлы и каталоги в текущем каталоге. Аргумент после pathявляется регулярным выражением, где точка обычно означает «любой символ», чтобы сделать его буквальной точкой, мы должны экранировать ее обратной косой чертой. Аргумент после -name не является регулярным выражением, но он расширяет символы подстановки как ?и *как оболочка.
Flimm 15.01.15

2
@frostschutz На самом деле, если подумать, я могу ошибаться, .имея особое значение.
Flimm

1
@ Flimm да, не нужно убегать .. Насколько мне известно, нужно только их экранировать: *, ?и [].
thdoan

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.
Роджер Пэйт

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

Исключает все скрытые каталоги и скрытые файлы в $ DIR


Это идеальный ответ. Он рекурсивно находит все файлы, но исключает позиции для каталогов и скрытых файлов. Спасибо!
KyleFarris

2

Ответ я первоначально размещен как «редактировать» на мой первоначальный вопрос выше:

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


Аналогично, но только для текущей папки:find . \( ! -regex './\..*' \) -type f -maxdepth 1 -print
phyatt

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). Не могли бы вы быть более многословным? Почему Globstar (= *) работает здесь и как? Что делает косая черта / делать?
сумасшедший о

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

@kenorb да-но: как этот однострочный поможет с первоначальным вопросом?
сумасшедший о

1
@nuttyaboutnatty Уточнил и добавил пример. Это помогает найти файлы, игнорирующие скрытый.
Кенорб

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.