Недавно я заметил, что спецификации POSIX дляfind
не включают -maxdepth
основной.
Для тех, кто не знаком с ним, цель -maxdepth
первичного состоит в том, чтобы ограничить, сколько уровней глубоко find
опустится. -maxdepth 0
приводит к обработке только аргументов командной строки; -maxdepth 1
будет обрабатывать результаты только внутри аргументов командной строки и т. д.
Как я могу получить поведение, эквивалентное -maxdepth
первичному, не относящемуся к POSIX, используя только указанные POSIX опции и инструменты?
(Примечание: конечно, я могу получить эквивалент -maxdepth 0
, просто используя -prune
в качестве первого операнда, но это не распространяется на другие глубины.)
-depth -2
,-depth 1
... можно рассматривать как лучший, чем подход GNU-maxdepth
/-mindepth
-maxdepth
/-mindepth
есть разумные альтернативы (обратите внимание, что-path
это недавнее дополнение к POSIX). Альтернативы для-timexy
или-mtime -3m
(или-mmin -3
) намного более громоздки. Некоторые любят-execdir
/ не-delete
имеют надежной альтернативы.Ответы:
Вы можете использовать,
-path
чтобы соответствовать заданной глубине и обрезать там. Напримербудет maxdepth 1, как
*
соответствует.
,*/*
соответствует./dir1
и*/*/*
соответствует,./dir1/dir2
который сокращается. Если вы используете абсолютный начальный каталог, вам нужно добавить ведущий/
к нему-path
.источник
/*
из конца шаблона, вынуть-o
оператор и получить тот же результат?*
совпадает/
, так что режиссерa/b/c/d/e
подойдет-path */*
, к сожалению.a/b/c/d/e
никогда не будет достигнуто , потому-prune
что будет применяться кa/b
....-prune
и-o
был удален. Если вы сохраняете-prune
проблему, проблема заключается в том, что*/*
они не будут сопоставляться с чем-либо на уровне выше maxdepth, например, с одним каталогомa
.Подход @ meuh неэффективен, так как он
-maxdepth 1
все еще позволяетfind
читать содержимое каталогов на уровне 1, чтобы впоследствии игнорировать их в противном случае. Он также не будет работать должным образом с некоторымиfind
реализациями (включая GNUfind
), если некоторые имена каталогов содержат последовательности байтов, которые не образуют допустимые символы в локали пользователя (например, для имен файлов в другой кодировке символов).это более канонический способ реализации GNU
-maxdepth 1
(или FreeBSD-depth -2
).Однако, как правило,
-depth 1
вы хотите (-mindepth 1 -maxdepth 1
), поскольку вы не хотите учитывать.
(глубина 0), и тогда это еще проще:Ибо
-maxdepth 2
это становится:И вот где вы бежите в недопустимых проблемах характера.
Например, если у вас есть каталог с именем,
Stéphane
ноé
он закодирован в кодировке iso8859-1 (он же latin1) (0xe9 байт), как это было наиболее распространенным в Западной Европе и Америке до середины 2000-х годов, то этот байт 0xe9 не является допустимый символ в UTF-8. Таким образом, в локалях UTF-8*
подстановочный знак (с некоторымиfind
реализациями) не будет совпадать, такStéphane
как*
равен 0 или более символов, а 0xe9 не является символом.Мой
find
(когда вывод идет на терминал) отображает этот недопустимый байт 0xe9, как?
указано выше. Вы можете видеть, чтоSt<0xe9>phane/Chazelas
не былоprune
d.Вы можете обойти это, выполнив:
Но обратите внимание, что это влияет на все настройки локали
find
и любого приложения, которое он запускает (например, с помощью-exec
предикатов).Теперь я действительно понимаю,
-maxdepth 2
но обратите внимание на то,??
как символ é во втором Стефане, правильно закодированный в UTF-8, отображается как байты 0xc3 0xa9 (рассматриваемые как два отдельных неопределенных символа в локали C) в кодировке é UTF-8. непечатаемые символы в локали C.И если бы я добавил a
-name '????????'
, я бы получил неправильный Стефан (тот, который закодирован в iso8859-1).Чтобы применить к произвольным путям вместо
.
, вы должны сделать:для
-mindepth 1 -maxdepth 1
или:для
-maxdepth 2
.Я бы все равно сделал:
Во-первых, потому что это делает пути короче, что снижает вероятность появления слишком длинных путей или слишком длинных списков аргументов, но также помогает обойти тот факт, что
find
не может поддерживать произвольные аргументы пути (кроме как-f
с FreeBSDfind
), так как он будет подавлен значения$dir
как!
или-print
...-o
В сочетании с отрицанием является обычным трюком для запуска двух независимых наборов-condition
/-action
вfind
.Если вы хотите запускать
-action1
на собрании файлов-condition1
и независимо-action2
на собрании файлов-condition2
, вы не можете сделать:Как
-action2
будет запускаться только для файлов, которые удовлетворяют обоим условиям.Также:
Как
-action2
не будет работать для файлов, которые отвечают обоим условиям.работает так же, как
\( ! -condition1 -o -action1 \)
и для истины для каждого файла. Это предполагает-action1
, что действие (например-prune
,-exec ... {} +
) всегда возвращает true . Для таких действий-exec ... \;
может возвращаться значение false , вы можете добавить другое,-o -something
где-something
это безопасно, но возвращает true, как-true
в GNUfind
или-links +0
или-name '*'
(хотя обратите внимание на проблему с недопустимыми символами выше).источник
Я столкнулся с проблемой, когда мне нужен был способ ограничения глубины при поиске по нескольким путям (а не просто
.
).Например:
Это привело меня к альтернативному подходу с использованием -regex. Суть это:
Итак, вышесказанное будет:
Без имени файла:
Наконец, для
-maxdepth 2
регулярного выражения изменяется на:'(dir1|dir2)/([^/]*/){0,1}[^/]*$'
источник
-maxdepth
будет работать с несколькими путями поиска.