Unix find: поиск исполняемых файлов
Какой тип параметра / флага я могу использовать с Unix find
команда, чтобы я искал исполняемые файлы?
9 ответов
На GNU версии find вы можете использовать -executable
:
find . -type f -executable -print
Для BSD-версий find вы можете использовать -perm
с +
и восьмеричная маска:
find . -type f -perm +111 -print
В этом контексте "+" означает "любой из этих битов установлен", а 111 - биты исполнения.
Обратите внимание, что это не идентично -executable
Предикат в GNU найти. Особенно, -executable
проверяет, что файл может быть выполнен текущим пользователем, в то время как -perm +111
просто проверяет, установлены ли какие-либо разрешения на выполнение.
Старые версии GNU find также поддерживают -perm +111
синтаксис, но с 4.5.12 этот синтаксис больше не поддерживается. Вместо этого вы можете использовать -perm /111
чтобы получить это поведение.
Наконечник шляпы @ gniourf_gniourf для gniourf_gniourf фундаментального заблуждения.
В этом ответе делается попытка дать обзор существующих ответов и обсудить их тонкости и относительные достоинства, а также предоставить справочную информацию, особенно в отношении переносимости.
Поиск исполняемых файлов может ссылаться на два разных варианта использования:
- ориентированный на пользователя: поиск файлов, которые могут быть выполнены текущим пользователем.
- file-centric: поиск файлов с установленными (одним или несколькими) исполняемыми битами разрешений.
Обратите внимание, что в любом сценарии может иметь смысл использовать find -L ...
вместо просто find ...
чтобы также найти символические ссылки на исполняемые файлы.
Обратите внимание, что простейший файлово-ориентированный случай - поиск исполняемых файлов с битом разрешений на исполняемый файл, установленным для ВСЕХ трех участников безопасности (пользователь, группа, другое) - обычно, но не обязательно, дает те же результаты, что и сценарий, ориентированный на пользователя, - и это важно понимать разницу.
Ориентированный на пользователя (-executable
)
Принятый ответ похвально рекомендует
-executable
IF IF GNUfind
доступен.- GNU
find
поставляется с большинством дистрибутивов Linux- В отличие от этого, платформы на базе BSD, включая macOS, поставляются с BSD find, который является менее мощным.
- Как требует сценарий,
-executable
соответствует только файлам, которые может выполнить текущий пользователь (есть крайние варианты. [1]).
- GNU
BSD
find
альтернатива предложенного принятого ответа (-perm +111
) отвечает на другой файлово-ориентированный вопрос (как говорится в самом ответе).- Используя только
-perm
ответить на вопрос, ориентированный на пользователя, невозможно, потому что необходимо связать личность пользователя и группы в файле с текущим пользователем, тогда как-perm
можно только проверить права доступа к файлу.
Использование только POSIXfind
особенности, вопрос не может быть дан ответ без привлечения внешних утилит. Таким образом, лучший
-perm
может сделать (само по себе) является приближением-executable
, Возможно, более близкое приближение, чем-perm +111
является-perm -111
, чтобы найти файлы с установленным исполняемым битом для ВСЕХ участников безопасности (пользователь, группа, другое) - это выглядит как типичный сценарий реального мира. В качестве бонуса, он также оказывается POSIX-совместимым (используйтеfind -L
чтобы включить символические ссылки, см. ниже для объяснения):find . -type f -perm -111 # or: find . -type f -perm -a=x
- Используя только
Ответ gniourf_gniourf обеспечивает истинный, переносимый эквивалент
-executable
, с помощью-exec test -x {} \;
Хотя и за счет производительности.Объединяя
-exec test -x {} \;
с-perm +111
(то есть файлы с хотя бы одним установленным исполняемым битом) могут повысить производительность в этомexec
не нужно вызывать для каждого файла (ниже используется POSIX-совместимый эквивалент BSD find-perm +111
/ GNU найти-perm /111
; см. ниже ниже для объяснения):find . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \) -exec test -x {} \; -print
Файлоцентричный (-perm
)
- Чтобы ответить на вопросы, связанные с файлами, достаточно использовать POSIX-совместимый
-perm
основной (известный как тест в GNU найти терминологию).-perm
позволяет проверять любые права доступа к файлам, а не только исполняемость.- Разрешения указываются в восьмеричном или символическом режимах. Восьмеричные моды - это восьмеричные числа (например,
111
), тогда как символические режимы - это строки (например,a=x
). - Символьные режимы идентифицируют участников безопасности как
u
(Пользователь),g
(группа) иo
(другое) илиa
сослаться на все три. Разрешения выражаются какx
например, для исполняемого файла и назначается принципалам с помощью операторов=
,+
а также-
; для полного обсуждения, включая восьмеричные режимы, см. спецификацию POSIX дляchmod
утилита - В контексте
find
:- Префикс режима с
-
(например,-ug=x
) означает: сопоставлять файлы, которые имеют все указанные разрешения (но соответствующие файлы могут иметь дополнительные разрешения). - Без префикса (например,
755
) означает: сопоставлять файлы с полным набором разрешений. - Предостережение: И GNU-поиск, и BSD-поиск реализуют дополнительный нестандартный префикс с логикой "любой из указанных битов разрешения", но делают это с несовместимым синтаксисом:
- BSD найти:
+
- GNU найти:
/
[2]
- BSD найти:
- Поэтому избегайте этих расширений, если ваш код должен быть переносимым.
- Префикс режима с
- Приведенные ниже примеры демонстрируют переносимые ответы на различные файловые вопросы.
Примеры файлово-ориентированных команд
Замечания:
- Следующие примеры являются POSIX-совместимыми, что означает, что они должны работать в любой POSIX-совместимой реализации, включая GNU find и BSD find; в частности, для этого необходимо:
- НЕ использовать префиксы нестандартного режима
+
или же/
, - Использование форм POSIX основных логических операторов:
!
для НЕ (GNU найти и BSD найти также позволяют-not
); Обратите внимание, что\!
используется в примерах для защиты!
из расширений истории оболочки-a
для AND (GNU find и BSD find также позволяют-and
)-o
для ИЛИ (GNU найти и BSD найти также позволяют-or
)
- НЕ использовать префиксы нестандартного режима
- В примерах используются символические режимы, потому что их легче читать и запоминать.
- С префиксом режима
-
,=
а также+
операторы могут использоваться взаимозаменяемо (например,-u=x
эквивалентно-u+x
- если вы не подадите заявку-x
позже, но в этом нет никакого смысла). - использование
,
включить частичные режимы; И логика подразумевается; например,-u=x,g=x
означает, что должен быть установлен как пользовательский, так и исполняемый бит группы. - Сами по себе режимы не могут выражать отрицательное сопоставление в смысле "сопоставлять, только если этот бит НЕ установлен"; Вы должны использовать отдельный
-perm
выражение с НЕ первичным,!
,
- С префиксом режима
- Обратите внимание, что найти праймериз (например,
-print
, или же-perm
; также известные как действия и тесты в GNU find), неявно объединяются с-a
(логическое И), и это-o
и, возможно, скобки (экранированные как\(
а также\)
для оболочки) необходимы для реализации логики ИЛИ. find -L ...
вместо простоfind ...
используется для того, чтобы также сопоставить символические ссылки с исполняемыми файлами-L
инструктирует find для оценки целей символических ссылок вместо самих символических ссылок; следовательно, без-L
,-type f
будет игнорировать символические ссылки в целом.
# Match files that have ALL executable bits set - for ALL 3 security
# principals (u (user), g (group), o (others)) and are therefore executable
# by *anyone*.
# This is the typical case, and applies to executables in _system_ locations
# (e.g., /bin) and user-installed executables in _shared_ locations
# (e.g., /usr/local/bin), for instance.
find -L . -type f -perm -a=x # -a=x is the same as -ugo=x
# The POSIX-compliant equivalent of `-perm +111` from the accepted answer:
# Match files that have ANY executable bit set.
# Note the need to group the permission tests using parentheses.
find -L . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \)
# A somewhat contrived example to demonstrate the use of a multi-principial
# mode (comma-separated clauses) and negation:
# Match files that have _both_ the user and group executable bit set, while
# also _not_ having the other executable bit set.
find -L . -type f -perm -u=x,g=x \! -perm -o=x
[1] Описание -executable
от man find
по состоянию на GNU найти 4.4.2:
Соответствует исполняемым файлам и каталогам, доступным для поиска (в смысле разрешения имен файлов). При этом учитываются списки контроля доступа и другие артефакты разрешений, которые тест -perm игнорирует. Этот тест использует системный вызов access(2) и поэтому может быть одурачен серверами NFS, которые выполняют сопоставление UID (или сжатие корня), так как многие системы реализуют access(2) в ядре клиента и поэтому не могут использовать информация отображения UID, хранящаяся на сервере. Поскольку этот тест основан только на результате системного вызова access(2), нет никакой гарантии, что файл, для которого этот тест будет успешно выполнен, действительно может быть выполнен.
[2] GNU находит версии старше 4.5.12, также разрешенный префикс +
, но это было сначала устарело и в конечном итоге удалено, потому что объединение +
с символическими режимами дает, скорее всего, неожиданные результаты из-за того, что интерпретируется как точная маска разрешений. Если вы (a) используете версию до 4.5.12 и (b) ограничиваетесь только восьмеричными режимами, вы можете избежать использования +
и с GNU find, и с BSD find, но это не очень хорошая идея.
Чтобы иметь еще одну возможность1 найти файлы, которые исполняются текущим пользователем:
find . -type f -exec test -x {} \; -print
(здесь есть тестовая команда, найденная в PATH, очень вероятно, /usr/bin/test
не встроенный).
1 Используйте это только если -executable
флаг find
не доступен! это немного отличается от -perm +111
решение.
Вы можете использовать -executable
тестовый флаг:
-executable
Matches files which are executable and directories which are
searchable (in a file name resolution sense).
find . -executable -type f
на самом деле не гарантирует, что файл является исполняемым, он найдет файлы с установленным битом выполнения. Если вы делаете
chmod a+x image.jpg
Приведенная выше находка будет думать, что image.jpg - исполняемый файл, даже если это действительно изображение JPEG с установленным битом выполнения.
Я обычно работаю над этим вопросом:
find . -type f -executable -exec file {} \; | grep -wE "executable|shared object|ELF|script|a\.out|ASCII text"
Если вы хотите, чтобы find действительно печатала купольную информацию об исполняемых файлах, вы можете сделать что-то вроде этого:
find . -type f -executable -printf "%i.%D %s %m %U %G %C@ %p" 2>/dev/null |while read LINE
do
NAME=$(awk '{print $NF}' <<< $LINE)
file -b $NAME |grep -qEw "executable|shared object|ELF|script|a\.out|ASCII text" && echo $LINE
done
В приведенном выше примере полный путь к файлу находится в последнем поле и должен отражать, где вы ищете его с помощью awk "NAME=$(awk '{print $NF}' <<< $LINE)", если имя файла было где-то еще в найти выходную строку вам нужно заменить "NF" на правильную числовую позицию. Если ваш разделитель не является пробелом, вы также должны указать awk, какой у вас разделитель.
Это сработало для меня и думал поделиться...
find ./ -type f -name "*" -not -name "*.o" -exec sh -c '
case "$(head -n 1 "$1")" in
?ELF*) exit 0;;
MZ*) exit 0;;
#!*/ocamlrun*)exit0;;
esac
exit 1
' sh {} \; -print
Поэтому, если вы действительно хотите найти исполняемые типы файлов (например, скрипты, двоичные файлы ELF и т. Д. И т. Д.), А не просто файлы с разрешением на выполнение, то вы, вероятно, захотите сделать что-то более похожее (где текущий каталог. Может быть заменен любым каталог, который вы хотите):
gfind . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print
Или для тех из вас, кто не использует macports (пользователи linux) или иным образом установил gnu find так, как вам нужно:
find . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print
Хотя, если вы работаете в OS X, он поставляется с небольшой утилитой, скрытой где-то под названием is_exec, которая в основном связывает этот маленький тест для вас, чтобы вы могли сократить командную строку, если найдете ее. Но этот способ является более гибким, поскольку вы можете легко заменить тест == тестом =~ и использовать его для проверки более сложных свойств, таких как исполняемые текстовые файлы или любую другую информацию, которую возвращает ваша файловая команда.
Точные правила цитирования здесь довольно непрозрачны, поэтому я просто заканчиваю работу над ними методом проб и ошибок, но я бы хотел услышать правильное объяснение.
Ну, простой ответ будет: "ваши исполняемые файлы находятся в каталогах, содержащихся в вашей переменной PATH", но это на самом деле не найдет ваши исполняемые файлы и может пропустить много исполняемых файлов в любом случае.
Я не знаю много о Mac, но я думаю, что "mdfind 'kMDItemContentType=public.unix-executetable'" может пропустить такие вещи, как интерпретируемые скрипты
Если для вас нормально найти файлы с установленными исполняемыми битами (независимо от того, являются ли они на самом деле исполняемыми), тогда это можно сделать
find . -type f -perm +111 -print
там, где поддерживается опция "-executable", дополнительный фильтр будет проверять acl и другие артефакты разрешений, но технически не сильно отличается от "-pemr +111".
Возможно, в будущем find будет поддерживать "-magic " и позволит вам явно искать файлы с определенным магическим идентификатором... но тогда вам нужно будет указать, чтобы все исполняемые форматы идентифицировали магический идентификатор.
Я не знаю о технически правильном простом выходе на Unix.
Это так смешно, что это не супер-легко... не говоря уже о невозможном. Руки вверх, я откладываю на Apple/Spotlight...
mdfind 'kMDItemContentType=public.unix-executable'
По крайней мере, это работает!
У меня была та же проблема, и ответ был в исходном коде dmenu: утилита stest, созданная для этой цели. Вы можете скомпилировать файлы 'stest.c' и 'arg.h', и это должно работать. Есть справочная страница для использования, которую я поместил туда для удобства:
STEST(1) General Commands Manual STEST(1)
NAME
stest - filter a list of files by properties
SYNOPSIS
stest [-abcdefghlpqrsuwx] [-n file] [-o file]
[file...]
DESCRIPTION
stest takes a list of files and filters by the
files' properties, analogous to test(1). Files
which pass all tests are printed to stdout. If no
files are given, stest reads files from stdin.
OPTIONS
-a Test hidden files.
-b Test that files are block specials.
-c Test that files are character specials.
-d Test that files are directories.
-e Test that files exist.
-f Test that files are regular files.
-g Test that files have their set-group-ID
flag set.
-h Test that files are symbolic links.
-l Test the contents of a directory given as
an argument.
-n file
Test that files are newer than file.
-o file
Test that files are older than file.
-p Test that files are named pipes.
-q No files are printed, only the exit status
is returned.
-r Test that files are readable.
-s Test that files are not empty.
-u Test that files have their set-user-ID flag
set.
-v Invert the sense of tests, only failing
files pass.
-w Test that files are writable.
-x Test that files are executable.
EXIT STATUS
0 At least one file passed all tests.
1 No files passed all tests.
2 An error occurred.
SEE ALSO
dmenu(1), test(1)
dmenu-4.6 STEST(1)