Вопрос или проблема
Существует ли переменная окружения, которую я могу установить, чтобы её могла считывать find
(WSL Ubuntu 20.XX LTS), чтобы она никогда не искала пути, которые содержат, например, node_module
или .git
, когда выполняется поиск?
Или это будет псевдоним или что-то, что мне нужно будет указывать каждый раз, когда я использую команду find
с -path
и -prune
?
В руководстве для моей реализации find
(find (GNU findutils) 4.10.0
) есть раздел ближе к концу под названием “ПЕРЕМЕННЫЕ ОКРУЖЕНИЯ”, который перечисляет следующее:
ПЕРЕМЕННЫЕ ОКРУЖЕНИЯ
LANG Устанавливает значение по умолчанию для переменных интернационализации,
которые не заданы или равны нулю.
LC_ALL Если установлено в непустую строку, переопределяет значения
всех остальных переменных интернационализации.
LC_COLLATE
Стандарт POSIX указывает, что эта переменная влияет
на сопоставление шаблонов, используемое для опции -name.
GNU find использует библиотечную функцию fnmatch(3), и
поддержка LC_COLLATE зависит от системной библиотеки.
Эта переменная также влияет на интерпретацию ответа на -ok;
в то время как переменная LC_MESSAGES выбирает
фактический шаблон, используемый для интерпретации ответа на
-ok, интерпретация любых выражений в квадратных скобках в
шаблоне будет зависеть от LC_COLLATE.
LC_CTYPE
Эта переменная влияет на обработку классов символов,
используемых в регулярных выражениях, а также с тестом -name,
если системная библиотечная функция fnmatch(3) поддерживает
это. Эта переменная также влияет на интерпретацию любых классов
символов в регулярных выражениях, используемых для интерпретации ответа на
подсказку, выданную -ok. Переменная окружения LC_CTYPE также будет
влиять на то, какие символы считаются невидимыми, когда
выводятся имена файлов; смотрите раздел НУЖДЫЕ ИМЕНА ФАЙЛОВ.
LC_MESSAGES
Определяет локаль, которая будет использоваться для интернационализированных
сообщений. Если переменная окружения POSIXLY_CORRECT
установлена, это также определяет интерпретацию ответа на
подсказку, сделанную действием -ok.
NLSPATH
Определяет местоположение каталогов сообщений интернационализации.
PATH Влияет на директории, которые ищутся для нахождения
исполняемых файлов, вызываемых -exec, -execdir, -ok и -okdir.
POSIXLY_CORRECT
Определяет размер блока, используемого для -ls и -fls. Если
POSIXLY_CORRECT установлено, блоки имеют размер 512 байт.
В противном случае они имеют размер 1024 байта.
Установка этой переменной также отключает сообщения об ошибках
(то есть подразумевает -nowarn) по умолчанию, потому что POSIX
требует, чтобы, кроме вывода для -ok, все
сообщения, печатаемые в stderr, были диагностическими и
должны приводить к ненулевому коду завершения.
Когда POSIXLY_CORRECT не установлено, -perm +zzz
обрабатывается так же, как -perm /zzz, если +zzz не является
допустимым символическим режимом. Когда POSIXLY_CORRECT установлено, такие конструкции
обрабатываются как ошибка.
Когда POSIXLY_CORRECT установлено, ответ на подсказку,
сделанную действием -ok, интерпретируется в соответствии с
каталогом сообщений системы, в отличие от собственных
переводов сообщений find.
TZ Влияет на часовой пояс, используемый для некоторых
директив формата, связанных со временем, в -printf и -fprintf.
Предположительно, если бы у него были какие-либо другие переменные, они были бы перечислены там, так что эта версия по крайней мере не имеет того, что вы запрашиваете, и вам действительно нужно было бы настроить псевдоним с использованием -prune
или просто фильтровать результаты после выполнения.
Ни одна реализация find
, которую я знаю, не имеет такой переменной окружения, но find
обычно использует общие библиотеки, связываемые во время выполнения динамическим компоновщиком.
find
обычно считывает содержимое каталогов, используя стандартную функцию readdir()
из C-библиотеки, и динамический компоновщик действительно запрашивает переменную окружения $LD_PRELOAD
(по крайней мере, на системах GNU) для списка других разделяемых объектов, которые нужно загрузить, с помощью которых вы можете переопределять функции из этих подключенных библиотек.
Если вы создадите файл hide-git.c
со следующим содержимым:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
struct dirent *readdir(DIR *dirp)
{
static struct dirent* (*orig) (DIR*);
struct dirent *entp;
if (!orig)
orig = (struct dirent* (*) (DIR*)) dlsym (RTLD_NEXT, "readdir");
if (!orig) abort();
do {
entp = (*orig)(dirp);
} while (entp && strcmp(entp->d_name, ".git") == 0);
return entp;
}
и скомпилируете его как:
cc -Wall -fPIC -shared -o hide-git.so hide-git.c -ldl
А затем выполните:
export LD_PRELOAD=/path/to/that/hide-git.so
Тогда запись .git
(любой файл с именем .git
, независимо от того, является ли он каталогом или нет) будет скрыта из результатов readdir()
и всего, что использует его для получения содержимого каталогов.
Пример:
$ mkdir -p {.git,.foo,bar}/{1..3}
$ ls -A
bar/ .foo/ .git/
$ find .
.
./.git
./.git/1
./.git/2
./.git/3
./.foo
./.foo/1
./.foo/2
./.foo/3
./bar
./bar/1
./bar/2
./bar/3
$ export LD_PRELOAD=~/hide-git.so
$ ls -A
bar/ .foo/
$ find .
.
./.foo
./.foo/1
./.foo/2
./.foo/3
./bar
./bar/1
./bar/2
./bar/3
Без использования этих трюков, вы всегда можете сделать:
find . '(' -name .git -prune ')' -o '(' ... ')' -print
Вместо:
find ...
.
Ответ или решение
Вопрос использования переменных окружения для управления поведением команды find
в Linux, в частности в WSL Ubuntu 20.XX LTS, достаточно интересен и требует понимания особенностей самой команды, а также доступных механизмов модификации ее поведения.
Использование переменных окружения
Как указано в вашем описании, документация для вашего экземпляра find
(GNU findutils 4.10.0) не упоминает переменные окружения, которые могут использоваться для исключения из поиска конкретных путей, таких как node_modules
или .git
. Таким образом, можно concluir, что в данной версии find
нет встроенной возможности конфигурирования поведения команды с помощью переменных окружения.
Альтернативные методы исключения путей
-
Создание алиаса: Один из простейших способов избежать поиска в определенных каталогах — это создать алиас для команды
find
, который будет включать нужные параметры. Например, вы можете добавить что-то подобное в ваш файл.bashrc
:alias find='find . \( -path "./node_modules" -o -path "./.git" \) -prune -o -print'
После добавления запись в
.bashrc
, не забудьте выполнить командуsource ~/.bashrc
, чтобы обновить терминал. -
Использование опций
-path
и-prune
: Если вы хотите запускать командуfind
без создания алиаса, то вы можете использовать параметры-path
и-prune
непосредственно в команде. Вот пример:find . \( -path "./node_modules" -o -path "./.git" \) -prune -o -print
Этот метод позволяет вам гибко настраивать поиск без необходимости создания алиасов.
Продвинутый метод через LD_PRELOAD
Как вы упомянули, можно воспользоваться механизмом LD_PRELOAD
, чтобы скрыть определенные директории из результата выполнения команды readdir
, который используют многие команды, включая find
.
Примерный процесс будет следующим:
-
Создайте файл
hide-git.c
с содержимым:#define _GNU_SOURCE #include <dlfcn.h> #include <dirent.h> #include <string.h> #include <stdlib.h> struct dirent *readdir(DIR *dirp) { static struct dirent* (*orig) (DIR*); struct dirent *entp; if (!orig) orig = (struct dirent* (*) (DIR*)) dlsym (RTLD_NEXT, "readdir"); if (!orig) abort(); // Проверка на наличие оригинальной функции do { entp = (*orig)(dirp); // Получаем следующую запись } while (entp && strcmp(entp->d_name, ".git") == 0); // Пропускаем .git return entp; // Возвращаем следующий элемент }
-
Скомпилируйте код:
cc -Wall -fPIC -shared -o hide-git.so hide-git.c -ldl
-
Установите переменную окружения
LD_PRELOAD
:export LD_PRELOAD=/path/to/hide-git.so
Теперь, при выполнении команды find
, директория .git
будет скрыта из результатов.
Заключение
Таким образом, хотя в GNU find
на вашей системе нет встроенной поддержки переменных окружения для исключения путей из поиска, существует несколько эффективных методов, чтобы решить эту задачу. Использование алиасов и параметров -path
и -prune
— наиболее простые и интуитивно понятные способы. В то время как продвинутые методы, такие как использование LD_PRELOAD
, предлагали бы большую гибкость, но требуют больше усилий и технической подготовки.
Этот подход позволит вам управлять поисковыми запросами в системе более эффективно и избежать нежелательных каталогов в результатах.