Пошук виконуваних файлів за допомогою команди find


113

Який тип параметрів / прапор я можу використовувати з командою Unix, findщоб шукати виконувані файли?


введіть 'знайти людину'. Я думаю, що "-executable" - це варіант, який ви хочете.
sje397

3
find -executable... але це не гарантує, що кожен перерахований файл насправді виконується
Вільям

1
Не всі реалізації програми findстворені рівними. Можливість, рекомендована @ sje397 та @William, може бути недоступною. Краще використовувати прийняте рішення, показане нижче.
LS


Мені не подобаються всі подані нижче пропозиції, які базуються на дозволах файлів. Аргументація: для моєї операційної системи GNU (Ubuntu) можна встановити прапор "x" (виконується), наприклад, текстовий файл ASCII. Жодна міміка не завадила успішно завершити цю операцію. Потрібно лише невелику помилку / помилку для декількох ненавмисних файлів, щоб отримати прапор x. Тому рішення gniourf_gniourf '- це мій особистий фаворит. Однак у цього недоліку є те, що для перекомпільованих виконуваних файлів потрібен емулятор або цільовий пристрій.
Na13-c

Відповіді:


173

У GNU версіях пошуку ви можете використовувати -executable:

find . -type f -executable -print

Для BSD версій знахідки, ви можете використовувати -permз +і вісімковій маскою:

find . -type f -perm +111 -print

У цьому контексті "+" означає "будь-який з цих бітів встановлений", а 111 - біти виконання.

Зауважте, що це не тотожне -executableприсудку в знаходженні GNU. Зокрема, -executableтестує те, що файл може бути виконаний поточним користувачем, тоді як -perm +111просто тестує, чи встановлені будь-які дозволи на виконання.

Старіші версії GNU також знаходять підтримку -perm +111синтаксису, але станом на 4.5.12 цей синтаксис більше не підтримується. Натомість ви можете використовувати -perm /111для отримання такої поведінки.


Помилка find: invalid mode ‘+111’findutils 4.5.11 4.fc20.
sourcejedi

1
@sourcejedi Дякую Я фактично говорив лише про не-GNU версії знаходження (зокрема, BSD), але старіші версії пошуку GNU насправді теж підтримували цей синтаксис. У нових версіях вам доведеться використовувати /замість них +. Дивіться оновлену відповідь для отримання більш детальної інформації.
Лоранс Гонсальвес

Справді, я неправильно прочитав вашу відповідь. Вибачте за те, що зробили це складніше :).
sourcejedi

Якщо символічні посилання на виконувані файли також повинні бути знайдені, включає в себе -Lваріант: find -L ....
mklement0

Мені знадобилося певний час, щоб зрозуміти наслідки "не ідентичного предикату -executable" та "просто тестує, якщо встановлені будь-які дозволи на виконання": Це означає, що вони -perm +111можуть дати помилкові позитиви , тобто файли, які поточний користувач насправді не може виконати. Там немає ніякого способу , щоб емулювати -executableшляхом тестування дозволів в поодинці, тому що потрібно, щоб зв'язати в файл користувачів і груп ідентичність з поточним користувачем .
mklement0

35

Порада капелюха до @ gniourf_gniourf для усунення основної помилки.

Ця відповідь намагається дати огляд існуючих відповідей та обговорити їх тонкощі та відносні достоїнства , а також надати довідкову інформацію , особливо щодо портативності .

Пошук файлів, які можна виконати, може стосуватися двох різних випадків використання :

  • орієнтований на користувача : знайдіть файли, які виконуються поточним користувачем .
  • файл-орієнтовані : знайти файли , які мають (один або більше) дозвіл на виконання біт набір .

Зауважте, що в будь-якому сценарії може бути доцільним використанняfind -L ... замість find ...того, щоб знайти символьні посилання на виконувані файли .

Зауважте, що найпростіший файл, орієнтований на файли - пошук виконавчих файлів із встановленим бітом дозволів, встановленим для ВСІХ трьох принципів безпеки (користувача, групи та інших) - як правило , але не обов'язково дасть ті самі результати, що й орієнтований на користувача сценарій - і це важливо зрозуміти різницю.

Користувач, орієнтований на користувача ( -executable)

  • Загальноприйнятий відповідь похвально рекомендує -executable, ЯКЩО GNU find доступний.

    • GNU findпоставляється з більшістю дистрибутивів Linux
      • Навпаки, платформи на базі BSD, включаючи macOS, оснащені BSD знахідкою, яка є менш потужною.
    • Як вимагає сценарій, -executableвідповідність лише файлам, які може виконувати поточний користувач (є крайові випадки. [1] ).
  • 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 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).
    • -permдозволяє перевірити на наявність будь-яких дозволів файлів, а не лише для виконання.
    • Дозвіл задається як восьмеричний, так і символічний режими . Вісімкові режими - восьмеричні числа (наприклад, 111), тоді як символьні режими - це рядки (наприклад, a=x).
    • Символічні режими ідентифікують принципів безпеки як u(користувач), g(група) та o(інші) або aпосилаються на всі три. Дозволу виражаються x, наприклад, для виконуваних файлів, наприклад, і призначаються принципалам за допомогою операторів =, +і -; для повного обговорення, включаючи восьмеричні режими, див . специфікацію POSIX для chmodутиліти .
    • У контексті find:
      • Приставка режиму з- (наприклад, -ug=x) означає: сірникові файли , які мають всі права доступу визначено (але відповідні файли можуть мати додаткові дозволи).
      • Наявність без префікса (наприклад 755) означає: матч файли , які мають цей повний, точний набір дозволів.
      • Caveat : І GNU find, і BSD find реалізують додатковий нестандартний префікс із логікою набору "БУДЬ-ЯК-З-Вказаного дозволу-бітів" , але це роблять з несумісним синтаксисом :
        • Знайдіть BSD: +
        • Знайдіть GNU: / [2]
      • Тому уникайте цих розширень, якщо ваш код повинен бути портативним .
  • Наведені нижче приклади демонструють портативні відповіді на різні запитання, орієнтовані на файли.

Приклади команд, орієнтованих на файли

Примітка:

  • Наступні приклади сумісні з POSIX , тобто вони повинні працювати в будь-якій сумісній з POSIX реалізацією, включаючи пошук GNU та BSD; конкретно, для цього потрібно:
    • НЕ використовуючи нестандартні префікси режиму +або /.
    • Використання POSIX форм праймерів логічного оператора :
      • !для NOT (GNU find і BSD find також дозволяють -not); Зауважте, що \!використовується в прикладах, щоб захистити !від розширення історії оболонок
      • -aдля AND (GNU find і BSD find також дозволяють -and)
      • -oдля АБО (GNU find та BSD find також дозволяють -or)
  • У прикладах використовується символічне режими, оскільки їх легше читати та запам’ятовувати.
    • З приставкою режимі -, то =і +оператори можуть бути взаємозамінними (наприклад, -u=xеквівалентно -u+x- якщо ви не застосовувати -xпізніше, але немає ніякого сенсу робити це).
    • Використовувати ,для приєднання до часткових режимів; І логіка мається на увазі; наприклад, -u=x,g=xозначає, що повинні бути встановлені як користувач, так і виконуваний біт групи.
    • Режими не можуть самі виражати негативну відповідність у значенні "збіг, лише якщо цей біт НЕ встановлений"; Ви повинні використовувати окреме -permвираз з НЕ первинним, !.
  • Зауважте, що праймеризовані знахідки (такі як -print, або -perm; також відомі як дії та тести в GNU find) неявно з'єднуються з -a(логічним AND), і що, -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 ігнорує. Цей тест використовує системний виклик доступу (2), і тому його можна обдурити серверами NFS, які виконують відображення UID (або кореневу скриньку), оскільки багато систем реалізують доступ (2) в ядрі клієнта і тому не можуть скористатися інформація відображення UID, що зберігається на сервері. Оскільки цей тест базується лише на результаті системного виклику доступу (2), немає гарантії, що файл, для якого цей тест успішно, може бути реально виконаний.

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


2
Найповніша відповідь ТА колись? ;)
andynormancx

@andynormancx :) Ну, з точки зору великої кількості очок кулі, я можу запропонувати цьому супернику .
mklement0

11

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

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

(команда тестування тут є тією, яку знайдено в PATH, швидше за все /usr/bin/test, не вбудованою).


1 Використовуйте це, лише якщо -executableпрапор findнедоступний! це тонко відрізняється від -perm +111рішення.


2
Це працює, але це досить повільно. Також, залежно від оболонки, вам, можливо, доведеться загортати або уникати власника місця файлу, наприклад, '{}'або \{\}.
Іонокласт Брігхем

1
@ mklement0 це не знайде команди, які виконуються мною, як -executableце робиться, як і моя команда.
gniourf_gniourf

1
Дякую, @gniourf_gniourf - у мене справді було кілька помилок. Я передрук вашого інший коментаря тут, тому що я по крайней мере , на даний момент видалення моєї відповіді (можливо , щоб воскреснути, якщо щось врятувати , ): " find . -type f -perm -u=xце НЕ еквівалент -executable: -executableвідповідає всім файлам, користувач може виконувати, і вони включають g+xякщо я в належній групі або o+x. Насправді -perm -u=xзнайду багато файлів, які користувач не може виконати, і пропустять декілька, які може виконати користувач. "
mklement0

1
@ IonoclastBrigham: Хоча цитувати {}- це гіпотетична необхідність (а цитування не шкодить), на практиці це не потрібно в оболонках, схожих на POSIX та csh. Ви знаєте , раковини , де вона буде необхідна?
mklement0

4
@IonoclastBrigham: Цікаво, дякую; так, в fish, {}дійсно, слід уникати як або, '{}'або \{\}. Зауважте, що bash, kshі zshнадайте такий же спосіб розширення брекетів; Однак, вони не друкувати без лапок фішки {} як (і , таким чином: немає необхідності бігти), тому що вони не вважають в дійсне вираження розпірки (вони вимагають , по крайней мере , 2 лексеми, або дійсного вираження числової послідовності), в той час як fish вважатиме діє скріплює вираз, що призводить до порожнього рядка. {}
mklement0

9

Ви можете використовувати -executableтестовий прапор:

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

4
-виконання - це нібито невідомий варіант.
насправді

4
Це було б розширення пошуку GNU? Оскільки тег є Unix, а не Linux, принаймні розширення GNU потрібно документувати як таке.
Джонатан Леффлер

3
Ця опція не підтримується командою пошуку BSD, знайденою принаймні в OS X. Це розширення GNU, але може підтримуватися іншими ароматами пошуку.
Іонокласт Брігхем

FWIW, я виявив, що це не на слісах 10, а на слізах> = 11 (трохи згоріло)
Пітер Тернер

Зауважте, що насправді це не всі приклади. У моєму випадку у мене був файл, який я мав, -rw-r-xr-xякий -executableне виявляє
Dezza

2

Це працювало для мене, і я думав поділитися ...

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

13
Лише на кілька тисяч справ більше, і ви знову вигадали file!
трійка

@tripleee +1. Класним буде це розширення:find ./ -mime application/x-sharedlib -o -mime application/x-dosexec
Даніел Алдер

@Daniel Alder, яку версію ви знайдете? Я не знайшов варіант -ime in find (GNU findutils) 4.4.2
AjayKumarBasuthkar

@tripleee +1. використання 'file' & / 'mimetype' є хорошою ідеєю або відкрийте для себе версію, яка підтримує -mime є кращою. Також цікаво, чи 'file' / 'mimetype' мають можливість фільтрувати та відображати лише виконувані файли.
AjayKumarBasuthkar

2
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 %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, що таке ваш роздільник.


1

Це так смішно, що це не надто просто ... не кажучи вже про неможливе . Руки вгору, відкладаю Apple / Spotlight ...

mdfind 'kMDItemContentType=public.unix-executable'

Принаймні це працює!


Приємно знати про mdfindOSX. Зауважте, що команда uour повідомляє виконуючі файли Unix для всієї системи . mdfind -onlyin . 'kMDItemContentType=public.unix-executable'Обмежує результати підтексту поточного каталогу. Незначні інтереси: обмеження пошуку лише певним каталогом (без папок), мабуть, не підтримується. Посилання на виконувані файли, очевидно, ніколи не включаються. Цікаво, що після mdfindтого, як файл знайшов виконуваний файл, згодом видалення виконуваного біта не вибирається.
mklement0

Я думаю, що я виявив помилки в тому, як Spotlight виявляє / виявляє виконувані файли Unix; Я подав помилку в Apple, а також на openradar.me/20162683 . Я закликаю вас - і все , хто цікавиться цією функціональність - також повідомити про помилку в помилку при bugreport.apple.com
mklement0

(Вибачте за коментар шквал; сподіваємось, вони зараз правильні) mdfind -onlyin . 'kMDItemContentType=public.unix-executable'поводиться так, як find . -type f -perm +111 -printробить. Тобто він знаходить файли з будь-яким набором виконуваних бітів, які можуть давати помилкові позитиви (хоча це може не бути проблемою на практиці) - істинно знаходити файли, які виконуються поточним користувачем, використовуючи BSD find, див. Відповідь @ gniourf_gniourf. findПеревага на базі рішення має перевагу в тому, що при бажанні ви можете знайти посилання на виконувані файли (опція -L), що, mdfindздавалося б, не може.
mklement0

1
@ mklement0 моя відповідь ухилилася від прикрас - спробувати вирішити проблему додому - але так, ви б майже ніколи не використовували цю форму "невпорядкованою". інший варіант - не впевнений, чи з’явиться його - добре старий глобус .. ls /Applications/**/*(*)у вашій (моїй?) zshоболонці
Алекс Сірий

Дякую за зручну zshпораду - не знав цього; (Здається , що ви можете або відповідати виконуваним файлам ( *) або символьних посилання ( @), але не обидва, правда?). Що стосується вашого початкового моменту: Дозвольте ще раз зазначити: find . -type f -perm +a=xзробить те, що mdfindробить ваша команда, забезпечуючи при цьому більшу гнучкість. Ви навіть можете переформулювати його на сумісність з POSIX.
mklement0

1

Ну, легка відповідь буде: "ваші виконувані файли знаходяться в каталогах, що містяться у вашій змінній PATH", але це дійсно не знайде ваші виконувані файли і все одно може пропустити багато виконуваних файлів.

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

Якщо ви добре знайдете файли з набором виконуваних бітів (незалежно від того, чи вони насправді виконуються), це добре робити

find . -type f -perm +111 -print

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

Можливо, в майбутньому пошук знайде підтримку "-magic" і дозволить вам явно шукати файли з певним магічним ідентифікатором ... але тоді вам доведеться вказати для тонкої настройки всіх виконуваних форматів магічного ідентифікатора.

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


1

Отже, якщо ви насправді хочете знайти виконавські типи файлів (наприклад, сценарії, бінарні файли ELF і т. Д. Тощо), а не просто файли з дозволом на виконання, то, ймовірно, ви хочете зробити щось подібне (де поточний каталог можна замінити будь-яким потрібний каталог):

 gfind . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print

Або для тих із вас, хто не використовує макпорти (користувачі Linux) або іншим чином встановлено gnu find як потрібно:

 find . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print

Хоча якщо ви перебуваєте на OS X, він постачається з невеликою утилітою, прихованою десь під назвою is_exec, яка в основному поєднує цей невеликий тест для вас, щоб ви могли скоротити командний рядок, якщо його знайдете. Але цей спосіб є більш гнучким, оскільки ви можете легко замінити тест == на тест = ~ і використовувати його для перевірки складних властивостей, таких як виконувані текстові файли простого тексту або будь-яку іншу інформацію, яку повертає ваша файлова команда.


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


0

У мене було те саме питання, і відповідь була у вихідному коді 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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.