Unix find: поиск исполняемых файлов

Какой тип параметра/флаг можно использовать с командой Unix find, чтобы я искал исполняемые файлы?

Ответ 1

В версиях GNU find вы можете использовать -executable:

find . -type f -executable -print

Для версий поиска BSD вы можете использовать -perm с + и восьмеричную маску:

find . -type f -perm +111 -print

В этом контексте "+" означает "любой из этих битов установлен", а 111 - биты выполнения.

Обратите внимание, что это не совпадает с предикатом -executable в поиске GNU. В частности, -executable проверяет, что файл может быть выполнен текущим пользователем, а -perm +111 просто проверяет, установлены ли разрешения на выполнение.

Более старые версии GNU find также поддерживают синтаксис -perm +111, но с 4.5.12 этот синтаксис больше не поддерживается. Вместо этого вы можете использовать -perm /111, чтобы получить это поведение.

Ответ 2

Совет шляпы @gniourf_gniourf для устранения фундаментального заблуждения.

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

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

  • ориентированный на пользователя: найдите файлы, которые исполняются текущим пользователем.
  • file-centric: найдите файлы, у которых есть (один или несколько) исполняемых разрешений бит.

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

Обратите внимание, что простейший файлоцентрический случай - поиск исполняемых файлов с битом исполняемых разрешений, установленным для ВСЕХ трех участников безопасности (пользователя, группы, другого) - обычно будет, но не обязательно даст те же результаты, что и сценарий, ориентированный на пользователя - и важно понять разницу.

Пользовательский (-executable)

  • принятый ответ похвально рекомендует -executable, если доступен GNU find.

    • GNU find поставляется с большинством дистрибутивов Linux
      • В отличие от BSD-основанных платформ, включая OSX, есть поиск BSD, который менее эффективен.
    • Как требует сценарий, -executable соответствует только файлам, которые может выполнить текущий пользователь (есть случаи краев. [1]).
  • Альтернатива BSD find, предлагаемая принятым ответом (-perm +111) , отвечает на другой, ориентированный на файл вопрос (поскольку сам ответ утверждает).

    • Использовать только -perm для ответа на пользовательский вопрос невозможно, потому что необходимо связать идентификатор пользователя и группы файла с текущим пользователем, тогда как -perm может только тестировать разрешения файла.
      Используя только функции POSIX find, на вопрос нельзя ответить без привлечения внешних утилит.
    • Таким образом, лучший -perm может (само по себе) является приближением of -executable. Возможно, более близкое приближение, чем -perm +111, есть -perm -111, чтобы найти файлы, у которых есть исполняемый бит, установленный для ВСЕХ участников безопасности (пользователя, группы, другой) - это наводит меня как типичный реальный - мирный сценарий. В качестве бонуса он также совместим с POSIX (используйте find -L для включения символических ссылок, см. Ниже для объяснения):

      find . -type f -perm -111  # or: find . -type f -perm -a=x
      
  • gniourf_gniourf answer предоставляет истинный переносимый эквивалент -executable, используя -exec test -x {} \;, хотя за счет производительности.

    • Объединение -exec test -x {} \; с -perm +111 (т.е. файлы с хотя бы одним исполняемым битовым набором) может помочь производительности в том, что exec не нужно вызывать для каждого файла (ниже используется POSIX-совместимый эквивалент BSD find -perm +111/GNU find -perm /111, см. ниже для объяснения):

      find . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \) -exec test -x {} \; -print
      

Файл-ориентированный (-perm)

  • Чтобы ответить на вопросы, ориентированные на файл, достаточно использовать POSIX-совместимый -perm основной (известный как тест в GNU find termology).
    • -perm позволяет вам проверять любые разрешения на доступ к файлам, а не только выполнимость.
    • Разрешения указаны как восьмеричные или символические режимы. Восьмеричные режимы представляют собой восьмеричные числа (например, 111), тогда как символические режимы являются строками (например, a=x).
    • Символьные режимы идентифицируют участников безопасности как u (пользователь), g (группа) и o (другие), или a для обозначения всех трех. Разрешения выражаются как x для исполняемого файла, например, и назначаются принципалам с использованием операторов =, + и -; для полного обсуждения, включая восьмеричные режимы, см. спецификацию POSIX для утилиты chmod.
  • В контексте find:
    • Префикс режима с - (например, -ug=x) означает: сопоставлять файлы, имеющие все указанные разрешения (но соответствующие файлы могут иметь дополнительные разрешения).
    • Наличие префикса НЕТ(например, 755) означает: файлы соответствия, которые имеют полный и точный набор разрешений.
    • Caveat: Поиск GNU и поиск BSD реализуют дополнительный, нестандартный префикс с - это ЛЮБОЙ из- логика с установленными разрешениями-бит-бит, но сделать это с помощью несовместимого синтаксиса:
      • BSD find: +
      • Поиск GNU: / [2]
    • Поэтому избегать этих расширений, если ваш код должен быть переносимым.
Нижеприведенные примеры демонстрируют переносные ответы на различные вопросы, связанные с файлами.

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

Примечание:

  • Следующие примеры соответствуют POSIX, что означает, что они должны работать в любой совместимой с POSIX реализации, включая поиск GNU и поиск BSD; в частности, это требует:
    • НЕ использовать префиксы нестандартного режима + или /.
    • Использование форм POSIX логических операторов:
      • ! для NOT (поиск GNU и поиск BSD также позволяют -not); обратите внимание, что \! используется в примерах, чтобы защитить ! от расширений истории оболочки
      • -a для AND (поиск GNU и поиск BSD также позволяют -and)
      • -o для OR (поиск GNU и поиск BSD также позволяют -or)
  • В примерах используются символические режимы, потому что их легче читать и запоминать.
    • С префиксом режима - операторы = и + могут использоваться взаимозаменяемо (например, -u=x эквивалентно -u+x - если вы не примените -x позже, но там нечего делать).
    • Используйте , для присоединения к частичным режимам; И логика подразумевается; например, -u=x,g=x означает, что должны быть установлены как пользовательский, так и исполняемый бит группы.
    • Режимы сами не могут выразить отрицательное соответствие в смысле "матч, только если этот бит НЕ установлен"; вы должны использовать отдельное выражение -perm с НЕ первичным, !.
  • Обратите внимание, что найти первичные элементы (такие как -print или -perm, также известные как действия и тесты в поиске GNU) неявно соединены с -a (логическим И) и что -o и, возможно, круглые скобки ( экранированные как \( и \) для оболочки) необходимы для реализации логики ИЛИ.
  • find -L ... вместо find ... используется для сопоставления символических ссылок с исполняемыми файлами
    • -L инструктирует найти для оценки целей символических ссылок вместо самих символических ссылок; поэтому без -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 find 4.4.2:

Соответствует исполняемым файлам и каталогам, которые доступны для поиска (в смысле разрешения имени файла). Это учитывает доступ           контрольных списков и других разрешений артефактов, которые игнорирует тест -mm. Этот тест использует системный вызов доступа (2), и поэтому может быть           обманутых серверами NFS, которые выполняют сопоставление UID (или root-squashing), поскольку многие системы реализуют доступ (2) в ядре клиента и поэтому не могут           используйте информацию отображения UID, хранящуюся на сервере. Поскольку этот тест основан только на результате системного вызова доступа (2), там           не гарантирует, что файл, для которого этот тест успешно завершен, может быть выполнен.

[2] GNU найти версии старше 4.5.12 также допускает префикс +, но это было сначала устарело и в конечном итоге удалено, потому что объединение + с символическими режимами дает вероятные результаты, которые дают неожиданные результаты из-за интерпретации в качестве точной маски разрешений. Если вы (а) запускаете версию до версии 4.5.12 и (б) ограничиваете себя только восьмеричными режимами, вы можете избежать использования + с помощью поиска GNU и поиска BSD, но это не очень хорошая идея.

Ответ 3

Вы можете использовать флаг проверки -executable:

-executable
              Matches files which are executable  and  directories  which  are
              searchable  (in  a file name resolution sense).

Ответ 4

Чтобы иметь еще одну возможность 1 найти файлы, которые исполняются текущим пользователем:

find . -type f -exec test -x {} \; -print

(здесь приведена тестовая команда, найденная в PATH, скорее всего, /usr/bin/test, а не встроенная).


1 Используйте это только в том случае, если флаг -executable find недоступен! это существенно отличается от решения -perm +111.

Ответ 5

Это сработало для меня и подумало о совместном использовании...

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

Ответ 6

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 . -type f -executable -printf "%i.%D %s %m %U %G %[email protected] %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)" если имя файла было в другом месте в строке вывода find, вам нужно заменить "NF" на правильную цифровую позицию. Если ваш разделитель не является пространством, вам также нужно указать awk, что ваш разделитель.

Ответ 7

Это смешно, что это не супер-легко... не говоря уже о невозможности. Руки вверх, я откладываю на Apple/Spotlight...

mdfind 'kMDItemContentType=public.unix-executable'

По крайней мере, он работает!

Ответ 8

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

Я мало что знаю о mac, но я думаю, что "mdfind" kMDItemContentType = public.unix-executable "может пропустить такие вещи, как интерпретируемые скрипты

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

find . -type f -perm +111 -print

где поддерживается опция "-executable", будет добавлен еще один фильтр, смотрящий на acl и другие артефакты разрешений, но технически не сильно отличающийся от "-pemr +111".

Возможно, в будущем find будет поддерживать "-magic" и позволит вам явно искать файлы с определенным идентификатором магии... но тогда вы бы haveto указать, чтобы удалить все исполняемые форматы магии id.

Я не знаю технически правильного легкого выхода на unix.

Ответ 9

У меня была одна и та же проблема, и ответ был в исходном коде dmenu: утилита установки, созданная для этой цели. Вы можете скомпилировать файлы '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)