Linux find исключить каталог из поиска

Обновлено: 02.07.2024

Я пытаюсь запустить команду find для всех файлов JavaScript, но как мне исключить конкретный каталог?

Вот код find , который мы используем.

Используйте переключатель -prune . Например, если вы хотите исключить каталог misc , просто добавьте -path ./misc -prune -o в свою команду поиска:

Вот пример с несколькими каталогами:

Здесь мы исключаем ./dir1 , ./dir2 и ./dir3 из текущего каталога, поскольку в выражениях find это действие, которое действует в соответствии с критериями -path dir1 -o -path dir2 -o -path dir3 (если dir1 или dir2 или dir3 ), с оператором AND с type -d .

Чтобы исключить имя каталога на любом уровне, используйте -name :

Если -prune у вас не работает, это будет:

Предостережение: требуется просмотр всех нежелательных каталогов.

Я считаю, что следующее легче рассуждать, чем другие предлагаемые решения:

Важное примечание: пути, которые вы вводите после -path , должны точно соответствовать тому, что find будет печатать без исключения. Если это предложение сбивает вас с толку, просто убедитесь, что вы используете полные пути во всей команде целиком , например: find /full/path/ -not \( -path /full/path/exclude/this -prune \) . . См. Примечание [1], если вы хотите лучше понять.

Внутри \( и \) - это выражение, которое будет точно build/external (см. Важное примечание выше) и, в случае успеха, избегает прохождения чего-либо ниже . Затем оно группируется в одно выражение с закрывающейся круглой скобкой и имеет префикс -not , который заставит find пропустить все, что было найдено в этом выражении.

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

Примечание [1] : если вы хотите исключить /tmp/foo/bar и запускаете поиск типа " find /tmp \(. ", вы должны указать -path /tmp/foo/bar . Если, с другой стороны, вы запускаете find как этот cd /tmp; find . \(. , тогда вы должны указать -path ./foo/bar .

Здесь явно возникает некоторая путаница относительно предпочтительного синтаксиса для пропуска каталога.

Мнение GNU

-prune не позволяет find спускаться в каталог. Простое указание -not -path все равно опустится в пропущенный каталог, но -not -path будет ложным всякий раз, когда find проверяет каждый файл.

Проблемы с -prune

-prune делает то, для чего предназначено, но есть кое-что, о чем вы должны позаботиться при его использовании.

find печатает сокращенный каталог.

  • ИСТИНА . Это предполагаемое поведение, оно просто не сводится к нему. Чтобы полностью не печатать каталог, используйте синтаксис, который логически его опускает.

-prune работает только с -print и никакими другими действиями.

  • НЕПРАВИЛЬНО . -prune работает с любым действием, кроме -delete . Почему не работает с удалением? Чтобы -delete работал, find необходимо пройти по каталогу в порядке DFS, поскольку -delete сначала удалит листья, а затем родительские листьев и т. д. Но для того, чтобы указать -prune , чтобы иметь смысл, find должен попасть в каталог и перестать спускаться по нему, что явно не имеет смысла с -depth или -delete вкл.

Производительность

Заключение

И синтаксис f10bit, и Daniel C Синтаксис Sobral выполнялся в среднем от 10 до 25 мсек. Синтаксис GetFree, который не использует -prune , занял 865 мс. Итак, да, это довольно крайний пример, но если вы заботитесь о времени выполнения и делаете что-то удаленно интенсивное, вам следует использовать -prune .

Обратите внимание, что Синтаксис Дэниела С. Собрала работает лучше двух синтаксисов -prune ; но я сильно подозреваю, что это результат некоторого кэширования, так как изменение порядка, в котором они выполнялись, приводило к противоположному результату, в то время как версия без удаления всегда была самой медленной.

Это единственный, который работал на меня.

Поиск "MyFile", исключая "Directory". Сделайте акцент на звезды *.

Один из вариантов - исключить все результаты, содержащие имя каталога, с помощью grep. Например:

Я предпочитаю обозначение -not . оно более читаемое:

Используйте параметр -prune. Итак, что-то вроде:

'-Type d -name proc -prune' ищет только каталоги с именем proc, которые нужно исключить.
«-O» - это оператор «ИЛИ».

-prune определенно работает и является лучшим ответом, поскольку предотвращает переход в каталог, который вы хотите исключить. -not -path , который по-прежнему выполняет поиск в исключенном каталоге, он просто не печатает результат, что может быть проблемой, если исключенный каталог является смонтированным сетевым томом или у вас нет разрешений.

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

: сначала укажите все аргументы, связанные с путями, например . -path './dir1' -prune -o

: мне больше всего удастся поставить -name, -iname, etc в качестве последней опции в этой группе. Например. -type f -iname '*.js'

: вы захотите добавить -print при использовании -prune

Вот рабочий пример:

Это формат, который я использовал для исключения некоторых путей:

Я использовал это, чтобы найти все файлы не по пути ". *":

Подход -path -prune также работает с подстановочными знаками в пути. Вот инструкция find, которая найдет каталоги для сервера git, обслуживающего несколько репозиториев git, без внутренних каталогов git:

Find начнет поиск файлов и каталогов в текущем каталоге, отсюда и find . .

Параметр -o обозначает логическое ИЛИ и разделяет две части команды:

Любой каталог или файл, который не является каталогом ./misc, не пройдет первую проверку -path ./misc . Но они будут проверены вторым выражением. Если их имя соответствует шаблону *.txt , они будут напечатаны из-за опции -print .

Когда find достигает каталога ./misc, этот каталог удовлетворяет только первому выражению. Таким образом, к нему будет применена опция -prune . Он сообщает команде find не исследовать этот каталог. Таким образом, любой файл или каталог в ./misc даже не будет исследован с помощью find, не будет проверяться на соответствие второй части выражения и не будет напечатан.

Чтобы исключить несколько каталогов:

Чтобы добавить каталоги, добавьте -o -path "./dirname/*" :

Но, возможно, вам следует использовать регулярное выражение, если нужно исключить много каталогов.

Хороший способ избежать печати сокращенных каталогов - использовать -print (также работает для -exec ) после правой части -or после -prune . Например, .

Напечатает путь ко всем файлам в текущем каталоге с расширением .j2, пропуская все скрытые каталоги. Аккуратно. Но он также распечатает полный путь к каждому пропущенному каталогу, как указано выше. Однако следующие нет, .

Потому что логически существует скрытый -and после оператора -iname и перед -print. Это привязывает его к правой части предложения -or из-за логического порядка операций и ассоциативности. Но в документации говорится, что существует скрытый -print , если он (или любой из его родственников . -print0 и т. Д.) Не указан. Так почему же нет левой части изображения -or ? По-видимому (и я не понял этого с первого чтения страницы руководства), это правда, если нет -print -или -exec ВЕЗДЕ, и в этом случае -print логически разбрызгивается так что все будет напечатано. Если хотя бы одна операция в стиле print выражена в любом предложении, все эти скрытые логические операции исчезнут, и вы получите только то, что вы указали. Честно говоря, я мог бы предпочесть все наоборот, но тогда find с только описательными операторами, по-видимому, ничего не сделает, так что я думаю, что это имеет смысл и так. Как упоминалось выше, все это работает и с -exec , поэтому ниже приводится полный список ls -la для каждого файла с желаемым расширением, но не перечисляется первый уровень каждого скрытого каталога .

Для меня (и других участников этой темы) синтаксис find довольно быстро становится довольно причудливым, поэтому я всегда добавляю скобки, чтобы УБЕДИТЬСЯ, что я знаю, что к чему привязано, поэтому я обычно создаю макрос для типизации и формы все такие заявления как .

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

Для рабочего решения (протестировано на Ubuntu 12.04 (Precise Pangolin)) .

Будет искать файлы MP3 в текущей папке и подпапках, кроме подпапки dir1.

. исключить dir1 И dir2

Вы также можете использовать регулярные выражения для включения / исключения некоторых файлов / каталогов вашего поиска, используя что-то вроде этого:

Это даст вам только все файлы js, vue, css и т.д., но исключая все файлы в папках node_modules и vendor .

Похоже, работает так же, как

И ИМО легче запомнить.

Для этого вы можете использовать опцию обрезки. Как например:

Или обратная опция grep «grep -v»:

TL; DR: проанализируйте свои корневые каталоги и настройте поиск оттуда, используя параметр -path <excluded_path> -prune -o . Не включайте завершающий / в конце исключенного пути.

find / -path /mnt -prune -o -name "*libname-server-2.a*" -print

Я считаю, что для эффективного использования find необходимо хорошо понимать структуру каталогов вашей файловой системы. На моем домашнем компьютере установлены жесткие диски емкостью несколько ТБ, причем примерно половина этого контента создается с помощью rsnapshot (т. Е. rsync ). Хотя выполняется резервное копирование на физически независимый (дублирующий) диск, он монтируется в корневом каталоге моей системы ( / ): /mnt/Backups/rsnapshot_backups/ :

Каталог /mnt/Backups/rsnapshot_backups/ в настоящее время занимает

60 млн файлов и папок; простой просмотр этого содержимого требует времени:

Таким образом, каждый раз, когда мне нужно найти файл в моем / (корневом) разделе, мне нужно иметь дело (по возможности избегать) обхода моего раздела с резервными копиями.

ПРИМЕРЫ

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

Решение 1

Допустим, я хочу найти системный файл libname-server-2.a , но не хочу искать в своих резервных копиях rsnapshot . Чтобы быстро найти системный файл, используйте исключаемый путь /mnt (т. Е. Используйте /mnt , а не /mnt/ , или /mnt/Backups , или . ):

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

Решение 2

РЕЗЮМЕ | ВЫВОДЫ

Используйте подход, проиллюстрированный в « решении 1 ».

Отмечая, что всякий раз, когда вы добавляете завершающий / к исключенному пути, команда find затем рекурсивно вводит (все эти) каталоги /mnt/* - что в моем случае из-за /mnt/Backups/rsnapshot_backups/* > подкаталоги, дополнительно включает

2,9 ТБ файлов для поиска! Если не добавлять завершающий / , поиск должен завершиться почти сразу (в течение нескольких секунд).

«Решение 2» ( . -not -path <exclude path> . ) аналогично, похоже, рекурсивно выполняет поиск по исключенным каталогам, не возвращая исключенных совпадений, но излишне расходуя это время поиска.

Поиск в этих резервных копиях rsnapshot :

Чтобы найти файл в одной из моих ежечасных / ежедневных / еженедельных / ежемесячных rsnapshot резервных копий):

Исключение вложенного каталога:

Здесь я хочу исключить вложенный каталог, например /mnt/Vancouver/projects/ie/claws/data/* при поиске с /mnt/Vancouver/projects/ :

В сторону: добавление -print в конце команды подавляет распечатку исключенного каталога:

Приведенный выше пример находит все файлы *.js в текущем каталоге, за исключением папок .git и .hg , независимо от глубины этих папок .git и .hg .

Примечание: это также работает:

Но я предпочитаю обозначение ** для согласованности с некоторыми другими инструментами, которые здесь не по теме.

Для меня это подходит на Mac:

Он исключает каталоги vendor и app/cache для имени поиска с суффиксом php .

Я использовал find , чтобы предоставить список файлов для xgettext , и хотел опустить конкретный каталог и его содержимое. Я пробовал много перестановок -path в сочетании с -prune , но не смог полностью исключить каталог, который я хотел удалить.

Хотя мне удалось игнорировать содержимое каталога, которое я хотел проигнорировать, find затем вернул сам каталог как один из результатов, что привело к сбою xgettext как результат (не принимает каталоги; только файлы).

Мое решение состояло в том, чтобы просто использовать grep -v , чтобы пропустить каталог, который мне не нужен в результатах:

Я не могу сказать наверняка, есть ли аргумент в пользу find , который будет работать на 100%. Использование grep было быстрым и легким решением после некоторой головной боли.

Для тех из вас, кто пользуется более старыми версиями UNIX и не может использовать -path или -not

Протестировано на SunOS 5.10 bash 3.2 и SunOS 5.11 bash 4.4

Следующие команды работают:

Если у вас возникли проблемы с поиском, используйте опцию -D tree , чтобы просмотреть информацию об анализе выражения.

Или -D all , чтобы увидеть всю информацию о выполнении.

Если кто-то изучает, как игнорировать сразу несколько путей. Вы можете использовать массивы bash (отлично работает с GNU bash, версия 4.4.20 (1) -release)

Также по какой-то причине вы не сможете игнорировать пути к каталогам / bin /.

А вот и общее решение:

Чтобы не набирать /path/to/seach/ несколько раз, заключите find в пару pushd .. popd .

Я пробовал команду выше, но ни один из тех, кто использовал "-prune", у меня не работал. В конце концов я попробовал это с помощью следующей команды:

Для того, что мне было нужно, он работал следующим образом: поиск landscape.jpg на всех серверах, начиная с корневого, и исключая поиск в каталоге /var :

find / -maxdepth 1 -type d | grep -v /var | xargs -I '<>' find '<>' -name landscape.jpg

find / -maxdepth 1 -type d перечисляет все d каталоги в /

С его помощью можно задавать различные составные условия для дальнейших действий над файлами.

Часто ипользуется как первый шаг перед копированием, перемещением, удалением, изменением файлов, соответсвующих определённым условиям.

Поиск

Найти и вывести на экран все файлы в директории

find
find .
find . -print

-name: Поиск по имени

Найти по полному имени в текущей директории

Если регистр не важен

Поиск по расширению

Найти по расширению файла с помощью wildcard *

-not: обратное условие

Найти в текущей директории все файлы кроме php

Несколько условий вместе

Найти все файлы, которые начинаются с log но не имеют расширения .txt

-o: Логическое или

Найти либо .html либо .php файлы

Найти и скопировать

Найти и сразу скопировать в текущую директорию

Найти в текущей директории

Удалить из текущей директории

Поиск по типу

Чтобы найти только файлы определённого типа выполните find с опцией type.

Подробнее о файлах в Linux читайте в статье «Типы файлов в Linux»

Уровни вложенности

Найти все ссылки только на верхнем уровне вложенности

find /etc -maxdepth 1 -type l

Поиск по размеру файла

Filesystem Size Used Avail Use% Mounted on /dev/sda1 1014M 194M 821M 20% /boot

Найти обычные файлы определённого размера

Чтобы найти обычные файлы нужно использовать -type f

find /boot -size +20000k -type f

find: ‘/boot/efi/EFI/centos’: Permission denied find: ‘/boot/grub2’: Permission denied /boot/initramfs-0-rescue-389ee10be1b38d4281b9720fabd80a37.img /boot/initramfs-3.10.0-1160.el7.x86_64.img /boot/initramfs-3.10.0-1160.2.2.el7.x86_64.img

Файлы бывают следующих типов:

- : regular file
d : directory
c : character device file
b : block device file
s : local socket file
p : named pipe
l : symbolic link

find /boot -size +10000k -type f

find: ‘/boot/efi/EFI/centos’: Permission denied find: ‘/boot/grub2’: Permission denied /boot/initramfs-0-rescue-389ee10be1b38d4281b9720fabd80a37.img /boot/initramfs-3.10.0-1160.el7.x86_64.img /boot/initramfs-3.10.0-1160.el7.x86_64kdump.img /boot/initramfs-3.10.0-1160.2.2.el7.x86_64.img /boot/initramfs-3.10.0-1160.2.2.el7.x86_64kdump.img

То же самое плюс показать размер файлов

find /boot -size +10000k -type f -exec du -h <> \;

find: ‘/boot/efi/EFI/centos’: Permission denied find: ‘/boot/grub2’: Permission denied 60M /boot/initramfs-0-rescue-389ee10be1b38d4281b9720fabd80a37.img 21M /boot/initramfs-3.10.0-1160.el7.x86_64.img 13M /boot/initramfs-3.10.0-1160.el7.x86_64kdump.img 21M /boot/initramfs-3.10.0-1160.2.2.el7.x86_64.img 14M /boot/initramfs-3.10.0-1160.2.2.el7.x86_64kdump.img

Поиск по началу имени файла

Обратите внимание, что в find, в отличие от grep , ставить перед началом названия никаких символов не нужно.

Поиск по части имени файла

Найти в проекте topbicyle все директории с qa в названии

Переместить определённые файлы но не директории

Переместить файлы начинающиеся на определённые символы в другую директорию, но не трогать директории с подобными названиями

-perm: поиск по правам доступа

-path: поиск путей

find . -path "./code/p*"

Пример укороченного результата

-prune: ограничить глубину

Если нужно посмотреть только поддиректории верхнего уровня - используется -prune

find . -path "./code/p*" -prune

Получили только поддиректории без их содержимого

Исключить директорию из поиска

Из предыдущего параграфа понятно, что с помощью prune можно исключить директорию из поиска.

find ./code -path "./code/p*" -prune -false -o -name "*index.php"

./code/js/errors/index.php ./code/js/index.php ./code/c/index.php ./code/cpp/index.php ./code/go/pointers/index.php ./code/go/declare_variable/index.php ./code/go/constants/index.php ./code/go/index.php ./code/java/index.php ./code/dotnet/index.php ./code/ruby/index.php ./code/theory/index.php ./code/index.php

-false нужен чтобы не выводить проигнорированные директории.

Ещё один способ исключить директорию из поиска

find ./code -name "*.php" -not -path "./code/p*"

find + sed

К результатам команды find можно сразу же применить sed

. означает, что ищем в текущей директории (и вложенных)

Эта команда заменяет везде

Если нужно не найти или заменить строку а показать название файла, в котором есть определённые символы - удобно воспользоваться связкой find + grep

Добавить в функцию my_function дополнительный аргумент - сразу в всех .php файлах.

Я пытаюсь запустить find команду для всех файлов JavaScript, но как исключить конкретный каталог?

Вот find код, который мы используем.

Это лучше использовать find . | while read -r file . . Кроме того, лучше принимать и одобрять ответы. в то время как чтение медленно, потому что в это быстрее @mpapis при чтении правильно обрабатывает полные строки с пробелами. Просто запустите в папке с файлами с пробелами в именах: for file in $(find .); do echo "$file"; done . Имена с пробелами разделены, чего мы не хотим.

Используйте -prune переключатель. Например, если вы хотите исключить misc каталог, просто добавьте -path ./misc -prune -o в команду find:

Вот пример с несколькими каталогами:

Здесь мы исключаем dir1 , dir2 и dir3 , так как в find выражениях это действие, которое действует по критериям -path dir1 -o -path dir2 -o -path dir3 (если dir1 или dir2 или dir3 ), а также с type -d .

Дальнейшие действия -o print , просто распечатать.

Хм. Это также не работает для меня, так как будет включать игнорируемый каталог "./misc" в выводе. @ Theuni Это, вероятно, не сработало для вас, потому что вы не добавили -print (или любое другое действие) явно после -name . В этом случае обе «стороны» -o печати заканчиваются, тогда как при использовании -print печатается только эта сторона. С man-страницы: Because -delete implies -depth, you cannot usefully use -prune and -delete together. Итак, как мне выполнить удаление с помощью find, если я хочу исключить определенные каталоги из удаления? Для того, чтобы удалить весь каталог непосредственно от использования результатов: find . -not -path "./.git*" . Использование ./dir* вместо ./dir/* удаляет каталог, а также содержимое из вывода. Этот вопрос и путаница в ответах свидетельствуют о том, насколько плохо пользовательский интерфейс find соответствует тому, что нужно людям.

Если у -prune вас не работает, это будет:

Предостережение: требует прохождения всех нежелательных каталогов.

Один из комментариев в принятом ответе указывает на проблему. -prune не исключает сам каталог, он исключает его содержимое, что означает, что вы получите нежелательную строку в выводе с исключенным каталогом. Отличный ответ. Я бы добавил к этому, что вы можете исключить каталог на ЛЮБОМ уровне, изменив первый . на * . таким образом find -name "*.js" -not -path "*/omitme/*" , файлы любого каталога с именем «omitme» будут опущены на любом уровне глубины. Тем не менее, он по-прежнему пересекает весь нежелательный каталог. Я добавляю свой собственный ответ. :-) Обратите внимание, однако, что опция сокращения не работает, только если вы не используете -print явно. Было бы лучше сказать «Это альтернатива использованию -prune». Ответы о том, что -prune явно не ошибочны, они просто не такие, как вы.

Я считаю, что следующее легче рассуждать, чем другие предлагаемые решения:

Важное примечание: пути, которые вы вводите после, -path должны точно соответствовать тому, что find будет напечатано без исключения. Если это предложение Вас смущает только убедитесь , что используются полные пути через из всей команды , как это: . Смотрите примечание [1], если вы хотите лучшего понимания. find /full/path/ -not \( -path /full/path/exclude/this -prune \) .

Внутри \( и \) это выражение, которое будет точно соответствовать build/external (см. Важное примечание выше), и, в случае успеха, позволит избежать обхода чего-либо ниже . Затем он группируется как одно выражение с экранированными скобками и с префиксом, -not который заставит find пропустить все, что соответствует этому выражению.

Кто-то может спросить, не добавит ли при добавлении -not все остальные файлы при -prune повторном появлении, и ответ - нет. То , как -prune работает то , что все , что, как только это будет достигнуто, то файлы ниже этого каталога постоянно игнорируются.

Примечание [1] : Если вы хотите исключить, /tmp/foo/bar и вы запускаете поиск, как это " find /tmp \(. ", то вы должны указать -path /tmp/foo/bar . Если, с другой стороны, вы запускаете find, как это, cd /tmp; find . \(. вы должны указать -path ./foo/bar .

Отличный ответ, спасибо. Это работает и является масштабируемым (читаемым) для нескольких исключений. Вы джентльмены и ученый, сэр. Спасибо за пример для нескольких исключений Это не работает, если я хочу использовать ключ -delete: find . -not \( -path ./CVS -prune \) -type f -mtime +100 -delete find: The -delete action atomatically turns on -depth, but -prune does nothing when -depth is in effect. If you want to carry on anyway, just explicitly use the -depth option. @Janis Вы можете использовать -exec rm -rf <> \; вместо -delete . Изучив вывод find , это действительно очевидно, но это сбило меня с толку. Если вы ищете в текущем каталоге (указав в . качестве пути поиска или не указывая один на всех), то вы , скорее всего , хотите , чтобы ваш шаблон после того, как -path начать с ./ , например: find -not \( -path ./.git -prune \) -type f . Более точный (и POSIX-совместимый) вариант этого метода: find searchdir \! \( -type d \( -path './excludedir/*' -o -path './excludedir2/*' -o -path './excludedir3/*' \) -prune \) следуют любые условия, которые должны соответствовать тому, что вы ищете.

Здесь явно есть некоторая путаница относительно того, каким должен быть предпочтительный синтаксис для пропуска каталога.

Мнение GNU

аргументация

-prune останавливается find от спуска в каталог. Простое указание -not -path будет все равно попадать в пропущенный каталог, но -not -path будет ложным, когда find проверяется каждый файл.

Проблемы с -prune

-prune делает то, для чего он предназначен, но все же есть некоторые вещи, о которых вы должны позаботиться, используя его.

find печатает сокращенный каталог.

  • TRUE Это намеченное поведение, оно просто не сходит в него. Чтобы вообще не печатать каталог, используйте синтаксис, который логически его опускает.

-prune работает только с -print и без других действий.

  • НЕ ПРАВДА . -prune работает с любым действием, кроме -delete . Почему это не работает с удалением? Для -delete работы find необходимо пройти по каталогу в порядке DFS, так -delete как сначала будут удалены листья, затем родители листьев и т. Д. Но для определения -prune смысла find необходимо обратиться к каталогу и прекратить его нисходящее движение, что явно не имеет смысла с -depth или -delete на.

Представление

Вывод

Оба синтаксис f10bit в и синтаксис Daniel C. Собрал в взяли 10-25ms бежать в среднем. Синтаксис GetFree , который не используется -prune , занял 865 мс. Итак, да, это довольно экстремальный пример, но если вы заботитесь о времени выполнения и делаете что-то дистанционно интенсивное, вы должны использовать -prune .

Обратите внимание, что синтаксис Даниэля С. Собрала был лучшим из двух -prune синтаксисов; но я сильно подозреваю, что это результат некоторого кеширования, так как переключение порядка, в котором выполнялись два процесса, приводило к противоположному результату, в то время как версия без обрезки всегда была самой медленной.

После нескольких тестов на этих двух -prune я могу сказать, что редко есть какая-либо разница. Имейте в виду, что какая команда запускается в первую очередь выиграет от производительности процессора, позднее снижение производительности процессора> приведет к незначительному замедлению (я чистил кэш перед каждой командой в соответствии с предложением @ndemou) Попробуйте переключить число среди name1() name2() name3() в тестовом скрипте @BroSlow выше, чтобы изменить порядок выполнения, чтобы получить визуальное представление о том, что я сказал. В реальной жизни это незаметно между этими двумя, хотя. Вы не должны быть -о, что означает или. так что вы обрезаете первый шаг, а потом забываете об этом в следующем.

Это единственный, который работал на меня.

Поиск "MyFile", исключая "Каталог". Сделайте акцент на звезды *.

Этот метод работает в macOS, а принятый ответ - нет. Я знаю, оригинальный вопрос для Linux. Обратите внимание, что вы можете добавить несколько ! -path '*/Directory/*' к вашей команде последовательно, чтобы игнорировать несколько каталогов

Один из вариантов - исключить все результаты, содержащие имя каталога, с помощью grep. Например:

Этот работал для меня, другие (которые используют -prune ) - нет. Медленно в больших результатах, но полезно в меньших наборах. Но как исключить несколько каталогов, используя grep? Конечно так: find . -name '*.js' | grep -v excludeddir | grep -v excludedir2 | grep -v excludedir3 но может быть какой-то один способ grep. Если вы хотите , чтобы выполнить несколько отбирает , то вы бы лучше писать его в виде регулярных выражений: egrep -v '(dir1|dir2|dir3)' . Однако в этом конкретном примере лучше было бы исключить каталоги внутри find себя. да, вам не нужны круглые скобки, и было бы лучше использовать ^, чтобы убедиться, что он совпадает с именем каталога в начале строки, например: find. имя * .js | egrep -v "^ \ ./ excludedir1 | ^ \ ./ excludedir2"

Я предпочитаю -not обозначения . это более читабельно:

Это не верно. Это не мешает find войти в каталог и просмотреть все файлы внутри. find . -iname '*' -and -not -path './somePath' не мешает входу в указанный каталог. Это помогло мне с .git path find . -iname '*' -not -path './.git/*' @rane: Точнее find . -not -path "*/.git*" было бы то, что вы хотите.

Используйте опцию -prune. Итак, что-то вроде:

'-Type d -name proc -prune' ищет только каталоги с именем proc, которые нужно исключить.
'-O' является оператором 'ИЛИ'.

Это единственное решение «найти», которое сработало для меня. Каталоги, которые я хотел исключить, НЕ находятся сразу под текущим рабочим каталогом. Однако добавление -print в конец может улучшить результаты. find . -type d -name .hg -prune -o -name data игнорирует содержимое (нескольких) .hg каталогов, но перечисляет .hg сами каталоги. При этом -print он только перечислил каталоги данных, которые я искал.

-prune определенно работает и является лучшим ответом, потому что он предотвращает спуск в каталог, который вы хотите исключить. -not -path который все еще ищет исключенный каталог, он просто не печатает результат, что может быть проблемой, если исключенный каталог является подключенным сетевым томом или у вас нет разрешений.

Сложность заключается в том, что find очень важно определить порядок аргументов, поэтому, если вы не получите их правильно, ваша команда может не сработать. Порядок аргументов обычно таков:

: Сначала поместите все аргументы, связанные с путем, например . -path './dir1' -prune -o

: У меня больше всего успехов, когда я ставлю -name, -iname, etc последний вариант в этой группе. Например -type f -iname '*.js'

: Вы хотите добавить -print при использовании -prune

Вот рабочий пример:

Это формат, который я использовал для исключения некоторых путей:

Я использовал это, чтобы найти все файлы не в пути ". *":

Я попробовал это, и это все еще спускается в каталоги, таким образом, скорость определенно не улучшена.

Подход -path -prune также работает с подстановочными знаками в пути. Вот оператор find, который найдет каталоги для сервера git, обслуживающего несколько репозиториев git, оставив внутренние каталоги git:

Чтобы исключить несколько каталогов:

Чтобы добавить каталоги, добавьте -o -path "./dirname/*" :

Но, возможно, вам следует использовать регулярное выражение , если нужно исключить много каталогов.

find начнет поиск файлов и каталогов в текущем каталоге, отсюда и find . .

-o Вариант обозначает логическое ИЛИ и разделяет две части команды:

Любой каталог или файл, который не является каталогом ./misc, не пройдет первый тест -path ./misc . Но они будут проверены против второго выражения. Если их имя соответствует шаблону, который *.txt они получают, из-за -print опции.

Когда find достигает каталога ./misc, этот каталог удовлетворяет только первому выражению. Так что -prune опция будет применена к нему. Он сообщает команде find не исследовать этот каталог. Таким образом, любой файл или каталог в ./misc даже не будет проверен командой find, не будет проверен на соответствие второй части выражения и не будет напечатан.

У каждого есть решение, но твое объяснило это лучше всего. Я был непреклонен, чтобы сначала использовалось -name, а не -path. Ваше объяснение было достаточно, чтобы прийти к тому, что я хотел. найти . -name "* .txt" -print -o -path ./misc -prune

Для рабочего решения (проверено на Ubuntu 12.04 (Precise Pangolin)) .

будет искать файлы MP3 в текущей папке и подпапках, за исключением подпапки dir1.

. чтобы исключить dir1 И dir2

Хорошая уловка для того, чтобы избежать печати сокращенных каталогов - использовать -print (работает -exec также) после правой стороны -or после -prune . Например, .

напечатает путь ко всем файлам под текущим каталогом с расширением `.j2", пропуская все скрытые каталоги. Аккуратно. Но он также напечатает на распечатке полный путь каждого каталога, который пропускается, как отмечено выше. Однако, следующее не .

потому что по логике есть скрытый -and после -iname оператора и перед -принтом. Это связывает его с правой частью -or предложения из-за логического порядка операций и ассоциативности. Но в документах говорится, что есть скрытое, -print если оно (или любой из его двоюродных братьев . -print0 и т. Д.) Не указано. Так почему же не левая часть -or печати? Очевидно (и я не понял этого после моего первого прочтения страницы руководства), это верно, если там нет -print -ЛИ -exec ВСЕГДА, и в этом случае -print логически разбрасывается так, что все печатается. Если даже ОДИН print операции стиля, выраженной в каком-либо предложении, все эти скрытые логические операции исчезают, и вы получаете только то, что вы уточнить. Честно говоря, я бы предпочел это наоборот, но потом find только описательных операторов, по-видимому, ничего не сделало бы, так что я думаю, что это имеет смысл, как есть. Как упомянуто выше, все это также работает -exec , поэтому следующее дает полный ls -la список для каждого файла с желаемым расширением, но не перечисляет первый уровень каждого скрытого каталога, .

Для меня (и других в этом потоке) find синтаксис довольно быстро становится довольно барочным, поэтому я всегда добавляю парены, чтобы УВЕРЕН, что я знаю, что с чем связано, поэтому я обычно создаю макрос для типа-способности и формирую все такие операторы как. ..

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

Я пытаюсь запустить find команда для всех файлов JavaScript, но как исключить определенный каталог?

здесь find код, который мы используем.

используйте переключатель чернослива, например, если вы хотите исключить

Если -prune не работает для вас, это:

я нахожу, что о следующем проще рассуждать, чем о других предлагаемых решениях:

это происходит из фактического случая использования, когда мне нужно было вызвать YUI-compressor на некоторых файлах, сгенерированных wintersmith, но оставить другие файлы, которые должны быть отправлены как есть.

внутри \( и \) - Это выражение, которое будет соответствовать ровно build/external (это не если ты find ./build , например, - вам нужно чтобы изменить его на ./build/external в таком случае), и будет, на успех,избегайте прохождения чего-либо ниже. Затем это группируется как одно выражение с экранированной скобкой и префиксом -not что будет find пропустить все, что соответствовало этому выражению.

можно спросить, если добавить -not не сделает все остальные файлы скрыты -prune появляется снова, и ответ-нет. Путь -prune работает, что все, что, как только это будет достигнуто, файлы ниже этого каталога постоянно игнорируются.

, что также легко расширить, чтобы добавить дополнительные исключения. Например:

здесь явно есть некоторая путаница относительно того, какой предпочтительный синтаксис для пропуска каталога должен быть.

мнение GNU

мышление

-prune остановка find от спуска в каталог. Просто укажите -not -path все равно спустится в пропустить, а -not -path будет false всякий раз, когда find проверяет каждый файл.

проблемы с -prune

-prune делает то, что он предназначен для, но все еще некоторые вещи, которые вы должны заботиться при использовании его.

find печать обрезанного каталога.

  • правда это предполагаемое поведение, оно просто не опускается в него. Чтобы избежать печати каталога в целом, используйте синтаксис, который логически опускает.

-prune работает только с -print и другие действия.

  • НЕ ТАК. -prune работает с любым действием, за исключением -delete . почему он не работает с delete? на -delete чтобы работать, find необходимо пройти каталог в порядке DFS, так как -delete сначала удалить листья, затем родители, листьев и т. д. Но для указания -prune смысл, find необходимо попасть в каталог и остановить его спуск, что явно не имеет смысла с -depth или -delete on.

производительность

вывод

и f10bit это и синтаксис Даниэля С. собрала потребовалось 10-25ms для запуска в среднем. GetFree-х, который не использует -prune , взял 865ms. Итак, да, это довольно экстремальный пример, но если вы заботитесь о времени выполнения и делаете что-то удаленно интенсивное, вы должны использовать -prune .

Примечание синтаксис Даниэля С. собрала выполнил лучшее из двух -prune синтаксисы; но я сильно подозреваю, что это результат некоторого кэширования при переключении порядок, в котором они выполнялись, приводил к противоположному результату, в то время как версия без чернослива всегда была самой медленной.

Очень важно уметь вовремя найти нужную информацию в системе. Конечно, все современные файловые менеджеры предлагают отличные функции поиска, но им не сравнится с поиском в терминале Linux. Он намного эффективнее и гибче обычного поиска, вы можете искать файлы не только по имени, но и по дате добавления, содержимому, а также использовать для поиска регулярные выражения.

Кроме того, с найденными файлами можно сразу же выполнять необходимые действия. В этой статье мы поговорим о поиске с помощью очень мощной команды find Linux, подробно разберем её синтаксис, опции и рассмотрим несколько примеров.

Основная информация о Find

Команда find - это одна из наиболее важных и часто используемых утилит системы Linux. Это команда для поиска файлов и каталогов на основе специальных условий. Ее можно использовать в различных обстоятельствах, например, для поиска файлов по разрешениям, владельцам, группам, типу, размеру и другим подобным критериям.

Утилита find предустановлена по умолчанию во всех Linux дистрибутивах, поэтому вам не нужно будет устанавливать никаких дополнительных пакетов. Это очень важная находка для тех, кто хочет использовать командную строку наиболее эффективно.

Команда find имеет такой синтаксис:

find [ папка] [ параметры] критерий шаблон [действие]

Папка - каталог в котором будем искать

Параметры - дополнительные параметры, например, глубина поиска, и т д

Критерий - по какому критерию будем искать: имя, дата создания, права, владелец и т д.

Шаблон - непосредственно значение по которому будем отбирать файлы.

Основные параметры команды find

Я не буду перечислять здесь все параметры, рассмотрим только самые полезные.

  • -P - никогда не открывать символические ссылки.
  • -L - получает информацию о файлах по символическим ссылкам. Важно для дальнейшей обработки, чтобы обрабатывалась не ссылка, а сам файл.
  • -maxdepth - максимальная глубина поиска по подкаталогам, для поиска только в текущем каталоге установите 1.
  • -depth - искать сначала в текущем каталоге, а потом в подкаталогах.
  • -mount искать файлы только в этой файловой системе.
  • -version - показать версию утилиты find.
  • -print - выводить полные имена файлов.
  • -type f - искать только файлы.
  • -type d - поиск папки в Linux.

Критерии

Критериев у команды find в Linux очень много, и мы опять же рассмотрим только основные.

  • -name - поиск файлов по имени.
  • -perm - поиск файлов в Linux по режиму доступа.
  • -user - поиск файлов по владельцу.
  • -group - поиск по группе.
  • -mtime - поиск по времени модификации файла.
  • -atime - поиск файлов по дате последнего чтения.
  • -nogroup - поиск файлов, не принадлежащих ни одной группе.
  • -nouser - поиск файлов без владельцев.
  • -newer - найти файлы новее чем указанный.
  • -size - поиск файлов в Linux по их размеру.

Примеры использования

А теперь давайте рассмотрим примеры find, чтобы вы лучше поняли, как использовать эту утилиту.

1. Поиск всех файлов

Показать все файлы в текущей директории:


Все три команды покажут одинаковый результат. Точка здесь означает текущую папку. В место неё можно указать любую другую.

2. Поиск файлов в определенной папке

Показать все файлы в указанной директории:


Искать файлы по имени в текущей папке:


Поиск по имени в текущей папке:

find . -name "testfile*"

Не учитывать регистр при поиске по имени:

find . -iname "TeStFile*"


3. Ограничение глубины поиска

Поиска файлов по имени в Linux только в этой папке:

find . -maxdepth 1 -name "*.php"

4. Инвертирование шаблона

Найти файлы, которые не соответствуют шаблону:

find . -not -name "test*"

5. Несколько критериев

Поиск командой find в Linux по нескольким критериям, с оператором исключения:

find . -name "test" -not -name "*.php"

Найдет все файлы, начинающиеся на test, но без расширения php. А теперь рассмотрим оператор ИЛИ:

find -name "*.html" -o -name "*.php"

Эта команда найдёт как php, так и html файлы.

6. Тип файла

По умолчанию find ищет как каталоги, так и файлы. Если вам необходимо найти только каталоги используйте критерий type с параметром d. Например:

find . -type d -name "Загрузки"


Для поиска только файлов необходимо использовать параметр f:

find . -type f -name "Загрузки"


6. Несколько каталогов

Искать в двух каталогах одновременно:

find ./test ./test2 -type f -name "*.c"

7. Поиск скрытых файлов

Найти скрытые файлы только в текущей папке. Имена скрытых файлов в Linux начинаются с точки:

find . -maxdepth 1 -type f -name ".*"


8. Поиск по разрешениям

Найти файлы с определенной маской прав, например, 0664:

find . -type f -perm 0664

Права также можно задавать буквами для u (user) g (group) и o (other). Например, для того чтобы найти все файлы с установленным флагом Suid в каталоге /usr выполните:

sudo find /usr -type f -perm /u=s


Поиск файлов доступных владельцу только для чтения только в каталоге /etc:

find /etc -maxdepth 1 -perm /u=r


Найти только исполняемые файлы:

find /bin -maxdepth 2 -perm /a=x

9. Поиск файлов в группах и пользователях

Найти все файлы, принадлежащие пользователю:

find . -user sergiy

Поиск файлов в Linux принадлежащих группе:

find /var/www -group www-data


10. Поиск по дате модификации

Поиск файлов по дате в Linux осуществляется с помощью параметра mtime. Найти все файлы модифицированные 50 дней назад:

Поиск файлов в Linux открытых N дней назад:

Найти все файлы, модифицированные между 50 и 100 дней назад:

find / -mtime +50 -mtime -100

Найти файлы измененные в течении часа:

11. Поиск файлов по размеру

Найти все файлы размером 50 мегабайт:

От пятидесяти до ста мегабайт:

find / -size +50M -size -100M

Найти самые маленькие файлы:

find . -type f -exec ls -s <> \; | sort -n -r | head -5

find . -type f -exec ls -s <> \; | sort -n | head -5

12. Поиск пустых файлов и папок

find /tmp -type f -empty


13. Действия с найденными файлами

Для выполнения произвольных команд для найденных файлов используется опция -exec. Например, для того чтобы найти все пустые папки и файлы, а затем выполнить ls для получения подробной информации о каждом файле используйте:

find . -empty -exec ls -ld <> \;


Удалить все текстовые файлы в tmp

find /tmp -type f -name "*.txt" -exec rm -f <> \;

Удалить все файлы больше 100 мегабайт:

find /home/bob/dir -type f -name *.log -size +100M -exec rm -f <> \;

Выводы

Вот и подошла к концу эта небольшая статья, в которой была рассмотрена команда find. Как видите, это одна из наиболее важных команд терминала Linux, позволяющая очень легко получить список нужных файлов. Ее желательно знать всем системным администраторам. Если вам нужно искать именно по содержимому файлов, то лучше использовать команду grep.

Читайте также: