Unix find: поиск исполняемых файлов - PullRequest
95 голосов
/ 16 декабря 2010

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

Ответы [ 10 ]

147 голосов
/ 16 декабря 2010

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

find . -type f -executable -print

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

find . -type f -perm +111 -print

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

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

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

29 голосов
/ 13 марта 2015

Наконечник шляпы @ @ 1002 * gniourf_gniourf для выяснения фундаментального заблуждения.

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

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

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

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

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

Ориентированный на пользователя (-executable)

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

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

    • Использование только -perm для ответа на user -центрический вопрос невозможно , потому что то, что нужно соотносит идентификатор пользователя и группы файла *1118* с текущего пользователя , тогда как -perm может проверять только разрешения файла *1123*.
      Используя только POSIX find функции , на вопрос невозможно ответить без привлечения внешних утилит.
    • Таким образом, лучшее, что может -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 find -perm /111; подробности см. ниже):

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

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

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

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

Примечание:

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

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

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

9 голосов
/ 16 декабря 2010

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

-executable
              Matches files which are executable  and  directories  which  are
              searchable  (in  a file name resolution sense).
8 голосов
/ 29 апреля 2014

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

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

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


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

2 голосов
/ 11 марта 2016
find . -executable -type f

на самом деле не гарантирует, что файл является исполняемым, он найдет файлы с установленным битом выполнения.Если вы сделаете

chmod a+x image.jpg

, то приведенная выше находка будет думать, что image.jpg - исполняемый файл, даже если это действительно изображение в формате JPEG с установленным битом выполнения.

Обычно я обхожу проблемуthis:

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, какой у вас разделитель. </p>

2 голосов
/ 28 ноября 2013

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

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
1 голос
/ 21 марта 2016

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

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

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

find . -type f -perm +111 -print

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

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

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

1 голос
/ 13 марта 2015

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

mdfind 'kMDItemContentType=public.unix-executable'

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

0 голосов
/ 05 апреля 2019

Так что если вы действительно хотите найти исполняемые типы файлов (например, скрипты, бинарные файлы 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, которая в основном связывает этот маленький тест для вас, чтобы вы могли сократить командную строку, если найдете ее. Но этот способ более гибкий, поскольку вы можете легко заменить тест == тестом = ~ и использовать его для проверки более сложных свойств, таких как исполняемые текстовые файлы или любые другие данные, которые возвращает ваша файловая команда.


Точные правила цитирования здесь довольно непрозрачны, поэтому я просто заканчиваю работу над ними методом проб и ошибок, но я бы хотел услышать правильное объяснение.

0 голосов
/ 26 июля 2016

У меня была такая же проблема, и ответ был в исходном коде 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)
...