Cerca i file eseguibili utilizzando il comando find


113

Che tipo di parametro / flag posso usare con il findcomando Unix in modo da cercare gli eseguibili?


digita "man find". Penso che "-executable" sia l'opzione che desideri.
sje397

3
find -executable... ma questo non garantisce che ogni file elencato venga effettivamente eseguito
William

1
Non tutte le implementazioni di findsono create uguali. L'opzione consigliata da @ sje397 e @William potrebbe non essere disponibile. È preferibile utilizzare la soluzione accettata mostrata di seguito.
LS


Non mi piacciono tutte le proposte mostrate di seguito che si basano sui permessi dei file. Argomentazione: per il mio sistema operativo GNU (Ubuntu) è possibile impostare il flag "x" (eseguibile) per esempio file di testo ASCII. Nessuna imitazione ha impedito il completamento con successo di questa operazione. È necessario solo un piccolo errore / bug per più file non intenzionali per ottenere l'assegnazione del flag x. Pertanto le soluzioni gniourf_gniourf sono le mie preferite. Ha tuttavia lo svantaggio che per eseguibili cross-compilati è necessario un emulatore o un dispositivo di destinazione.
Na13-c

Risposte:


173

Nelle versioni GNU di find puoi usare -executable:

find . -type f -executable -print

Per le versioni BSD di find, è possibile utilizzare -permcon +ed un ottale maschera:

find . -type f -perm +111 -print

In questo contesto "+" significa "uno qualsiasi di questi bit è impostato" e 111 è il bit di esecuzione.

Nota che questo non è identico al -executablepredicato in GNU find. In particolare, -executableverifica che il file possa essere eseguito dall'utente corrente, mentre -perm +111verifica solo se sono impostati i permessi di esecuzione.

Anche le versioni precedenti di GNU supportano la -perm +111sintassi, ma a partire dalla 4.5.12 questa sintassi non è più supportata. Invece, puoi usare -perm /111per ottenere questo comportamento.


Errore find: invalid mode ‘+111’su findutils 4.5.11 4.fc20.
sourcejedi

1
@sourcejedi Thanks. In realtà stavo parlando solo di versioni non GNU di find (BSD, in particolare), ma le versioni precedenti di GNU find supportavano anche quella sintassi. Nelle versioni più recenti dovrai usare al /posto di +. Vedi la risposta aggiornata per maggiori dettagli.
Laurence Gonsalves

In effetti, ho letto male la tua risposta. Ci scusiamo per aver reso tutto più complicato :).
sourcejedi

Se i collegamenti simbolici ai file eseguibili dovrebbero essere trovati, includere l' -Lopzione di: find -L ....
mklement0

Mi c'è voluto un po 'per capire le implicazioni di "non identico al predicato -executable" e "solo test se qualsiasi sono impostate autorizzazioni di esecuzione": Significa che -perm +111può dare falsi positivi , cioè i file che l'utente corrente non può effettivamente eseguire. Non c'è modo di emulare -executabletestando solo le autorizzazioni, perché ciò che serve è mettere in relazione l' identità dell'utente e del gruppo del file con l' utente corrente .
mklement0

35

Punta di cappello a @ gniourf_gniourf per aver chiarito un malinteso fondamentale.

Questa risposta cerca di fornire una panoramica delle risposte esistenti e di discutere le loro sottigliezze e relativi meriti , nonché di fornire informazioni di base , soprattutto per quanto riguarda la portabilità .

La ricerca di file eseguibili può fare riferimento a due casi d'uso distinti :

  • incentrato sull'utente : trova i file eseguibili dall'utente corrente .
  • incentrato sui file : trova i file che hanno (uno o più) bit di autorizzazione eseguibili impostati .

Nota che in entrambi gli scenari può avere senso usarefind -L ... invece che solo find ...per trovare anche collegamenti simbolici agli eseguibili .

Si noti che il caso più semplice incentrato sui file, ovvero la ricerca di eseguibili con il bit di autorizzazioni eseguibile impostato per TUTTE e tre le entità di sicurezza (utente, gruppo, altro), in genere , ma non necessariamente, produrrà gli stessi risultati dello scenario incentrato sull'utente, ed è importante per capire la differenza.

Incentrato sull'utente ( -executable)

  • La risposta accettata raccomanda lodevolmente -executable, IF GNU find è disponibile.

    • GNU findviene fornito con la maggior parte delle distribuzioni Linux
      • Al contrario, le piattaforme basate su BSD, incluso macOS, vengono fornite con BSD find, che è meno potente.
    • Come richiesto dallo scenario, -executablecorrisponde solo ai file che l' utente corrente può eseguire (ci sono casi limite. [1] ).
  • L' alternativa BSD find offerta dalla risposta accettata ( -perm +111) risponde a una domanda diversa , centrata sul file (come afferma la risposta stessa).

    • Utilizzare solo -permper rispondere alla domanda incentrata sull'utente è impossibile , perché ciò che è necessario è correlare l' utente del file e l'identità del gruppo all'utente corrente , mentre -permpuò solo testare i permessi del file .
      Utilizzando solo le funzionalità POSIXfind , non è possibile rispondere alla domanda senza coinvolgere utilità esterne.
    • Quindi, il meglio che -permpuò fare (da solo) è un'approssimazione di -executable. Forse un'approssimazione più vicina di quanto non lo -perm +111sia-perm -111 , in modo da trovare file con il bit eseguibile impostato per TUTTE le entità di sicurezza (utente, gruppo, altro) - questo mi sembra il tipico scenario del mondo reale. Come bonus, sembra anche essere conforme a POSIX (da usare find -Lper includere collegamenti simbolici, vedere più avanti per una spiegazione):

      find . -type f -perm -111  # or: find . -type f -perm -a=x
  • La risposta di gniourf_gniourf fornisce un vero equivalente portatile-executable dell'uso-exec test -x {} \;, anche se a scapito delle prestazioni .

    • La combinazione -exec test -x {} \; con -perm +111(cioè, file con almeno un bit eseguibile impostato) può aiutare le prestazioni in quanto execnon è necessario invocare per ogni file (il seguente utilizza l'equivalente conforme a POSIX di BSD find -perm +111/ GNU find -perm /111; vedi più avanti per una spiegazione) :

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

Incentrato sui file ( -perm)

  • Per rispondere a domande incentrate sui file , è sufficiente utilizzare il -permprimario conforme a POSIX (noto come test in GNU find terminology).
    • -permti consente di testare qualsiasi autorizzazione sui file, non solo l'eseguibilità.
    • Le autorizzazioni sono specificate come modalità ottale o simbolica . I modi ottali sono numeri ottali (ad esempio, 111), mentre i modi simbolici sono stringhe (ad esempio, a=x).
    • Le modalità simboliche identificano le entità di sicurezza come u(utente), g(gruppo) e o(altro) o aper fare riferimento a tutte e tre. Permessi vengono indicati come xper eseguibile, per esempio, e assegnati ai principal utilizzando gli operatori =, +e -; per una discussione completa, comprese le modalità ottali, vedere le specifiche POSIX per l' chmodutilità .
    • Nel contesto di find:
      • Prefissare una modalità con- (ad es. -ug=x) Significa: abbinare i file che hanno tutti i permessi specificati (ma i file corrispondenti potrebbero avere permessi aggiuntivi).
      • Non avere alcun prefisso (ad esempio 755) significa: abbinare i file che hanno questo insieme completo ed esatto di autorizzazioni.
      • Avvertenza : sia GNU find che BSD find implementano un prefisso aggiuntivo non standard con logica ANY-of-the-permission-bits-set specificata , ma lo fanno con una sintassi incompatibile :
        • BSD trova: +
        • Ricerca GNU: / [2]
      • Pertanto, evita queste estensioni, se il tuo codice deve essere portabile .
  • Gli esempi seguenti dimostrano le risposte portatili a varie domande incentrate sui file.

Esempi di comandi incentrati sui file

Nota:

  • I seguenti esempi sono conformi a POSIX , il che significa che dovrebbero funzionare in qualsiasi implementazione compatibile con POSIX, inclusi GNU find e BSD find; in particolare, ciò richiede:
    • NON utilizzare prefissi in modalità non standard +o /.
    • Utilizzando le forme POSIX delle primarie dell'operatore logico :
      • !per NOT (GNU find e BSD find consentono anche -not); si noti che \!viene utilizzato negli esempi per proteggere !dalle espansioni della cronologia della shell
      • -aper AND (GNU find e BSD find consentono anche -and)
      • -oper OR (GNU find e BSD find consentono anche -or)
  • Gli esempi utilizzano modalità simboliche , perché sono più facili da leggere e ricordare.
    • Con il prefisso mode -, gli operatori =e +possono essere usati in modo intercambiabile (ad esempio, -u=xè equivalente a -u+x- a meno che non si applichi in -xseguito, ma non ha senso farlo).
    • Utilizzare ,per partecipare a modalità parziali; E la logica è implicita; ad esempio, -u=x,g=xsignifica che devono essere impostati sia l'utente che il bit eseguibile di gruppo.
    • Le modalità non possono esprimere esse stesse una corrispondenza negativa nel senso di "corrispondenza solo se questo bit NON è impostato"; è necessario utilizzare un separato -permespressione con la NON primaria, !.
  • Si noti che i primari di find (come -print, o -perm; noti anche come azioni e test in GNU find) sono implicitamente uniti con -a(AND logico) e che -oe possibilmente parentesi (con escape come \(e \)per la shell) sono necessarie per implementare la logica OR.
  • find -L ...invece di solo find ...è usato per abbinare anche i collegamenti simbolici agli eseguibili
    • -Lordina a find di valutare gli obiettivi dei collegamenti simbolici invece dei collegamenti simbolici stessi; quindi, senza -L, -type fignorerebbe del tutto i collegamenti simbolici.
# 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] Descrizione di -executableda a man findpartire da GNU find 4.4.2:

Corrisponde ai file che sono eseguibili e alle directory che sono ricercabili (in un senso di risoluzione del nome file). Questo tiene conto degli elenchi di controllo degli accessi e di altri artefatti dei permessi che il test -perm ignora. Questo test fa uso della chiamata di sistema access (2), e quindi può essere ingannato dai server NFS che eseguono la mappatura UID (o root-squash), poiché molti sistemi implementano l'accesso (2) nel kernel del client e quindi non possono farne uso le informazioni di mappatura UID contenute nel server. Poiché questo test si basa solo sul risultato della chiamata di sistema access (2), non vi è alcuna garanzia che un file per il quale questo test ha esito positivo possa essere effettivamente eseguito.

[2] GNU find versioni precedenti alla 4.5.12 consentivano anche il prefisso +, ma questo è stato prima deprecato e alla fine rimosso, perché la combinazione +con le modalità simboliche produce probabilmente risultati inaspettati poiché viene interpretata come una maschera di autorizzazioni esatte . Se voi (a) corsa su una versione prima 4.5.12 e (b) se stessi limitare a ottale modalità solo, si potrebbe farla franca con l'utilizzo +con entrambe GNU e BSD trovare ritrovamento, ma non è una buona idea.


2
La risposta SO più completa di sempre? ;)
andynormancx

@andynormancx :) Bene, in termini di numero di punti elenco, posso offrire questo concorrente .
mklement0

11

In modo da avere un'altra possibilità 1 per trovare i file che sono eseguibili dall'utente corrente:

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

(il comando di test qui è quello che si trova in PATH, molto probabilmente /usr/bin/test, non quello integrato).


1 Usalo solo se la -executablebandiera di findnon è disponibile! questo è leggermente diverso dalla -perm +111soluzione.


2
Funziona, ma è piuttosto lento. Inoltre, a seconda della shell, potrebbe essere necessario eseguire il wrapping o eseguire l'escape del segnaposto del nome del file, come '{}'o \{\}.
Ionoclast Brigham

1
@ mklement0 questo non troverà i comandi che sono eseguibili da me come -executablefa o come fa il mio comando.
gniourf_gniourf

1
Grazie, @gniourf_gniourf - Ho davvero avuto alcune idee sbagliate lì. Sto ristampando il tuo altro commento qui, perché almeno per ora sto cancellando la mia risposta (forse per essere resuscitato, SE c'è qualcosa di salvabile): " nonfind . -type f -perm -u=x è l'equivalente di : corrisponde a tutti i file che l'utente può eseguire, e questi includono se sono nel gruppo corretto o . In realtà troverà molti file che l'utente non può eseguire e ne mancheranno alcuni che l'utente può eseguire. " -executable-executableg+xo+x-perm -u=x
mklement0

1
@IonoclastBrigham: Sebbene la citazione {}sia una necessità ipotetica (e la citazione non guasta), in pratica non è necessaria nelle shell tipo POSIX e csh. Conosci le conchiglie dove è richiesto?
mklement0

4
@IonoclastBrigham: interessante, grazie; quindi, in fish, {}deve effettivamente essere evitato come '{}'o \{\}. Notare che bash, kshe zshforniscono lo stesso tipo di espansione delle parentesi graffe; tuttavia, stampano il token non quotato così {} com'è (e quindi: non c'è bisogno di eseguire l'escape), perché NON lo considerano un'espressione di parentesi graffa valida (richiedono almeno 2 token o un'espressione di sequenza numerica valida), mentre fish ritiene {}una parentesi graffa valida espressione che risulta nella stringa vuota .
mklement0

9

Puoi usare il -executableflag di prova:

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

4
-executable è presumibilmente un'opzione sconosciuta.
beh, in realtà il

4
Sarebbe un'estensione GNU Find? Poiché il tag è Unix, non Linux, almeno un'estensione GNU deve essere documentata come tale.
Jonathan Leffler

3
Questa opzione non è supportata dal comando BSD find che si trova almeno su OS X. Questa è un'estensione GNU, ma potrebbe essere supportata da altri tipi di find.
Ionoclast Brigham

FWIW, ho scoperto che questo non è su sles 10, ma su sles> = 11 (mi sono un po 'scottato)
Peter Turner

Notare che questo in realtà non ottiene tutti gli esempi. Nel mio caso ho avuto un file che ho posseduto da -rw-r-xr-xcui -executablenon rileva
Dezza

2

Questo ha funzionato per me e ho pensato di condividere ...

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
Solo alcune migliaia di casi in più, e ti sarai reinventato file!
tripla

@tripleee +1. Bella sarebbe questa estensione:find ./ -mime application/x-sharedlib -o -mime application/x-dosexec
Daniel Alder

@Daniel Alder, quale versione di find usi? Non ho trovato l'opzione -mime in find (GNU findutils) 4.4.2
AjayKumarBasuthkar

@tripleee +1. utilizzare 'file' e / 'mimetype' è una buona idea o scoprire trova la versione che supporta -mime è meglio, anche chiedendosi se 'file' / 'mimetype' hanno l'opzione per filtrare e visualizzare solo gli eseguibili.
AjayKumarBasuthkar

2
find . -executable -type f

non garantisce realmente che il file sia eseguibile, troverà i file con il bit di esecuzione impostato. Se fate

chmod a+x image.jpg

la ricerca sopra penserà che image.jpg sia un eseguibile anche se in realtà è un'immagine jpeg con il bit di esecuzione impostato.

In genere aggiro il problema con questo:

find . -type f -executable -exec file {} \; | grep -wE "executable|shared object|ELF|script|a\.out|ASCII text"

Se vuoi che la ricerca stampi effettivamente le informazioni della cupola sui file eseguibili, puoi fare qualcosa del genere:

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

Nell'esempio precedente il percorso completo del file si trova nell'ultimo campo e deve riflettere dove lo cerchi con awk "NAME = $ (awk '{print $ NF}' <<< $ LINE)" se il nome del file era altrove in la stringa di output di ricerca è necessario sostituire "NF" con la posizione numerica corretta. Se il tuo separatore non è spazio, devi anche dire a awk qual è il tuo separatore.


1

È COSÌ ridicolo che questo non sia semplicissimo ... figuriamoci quasi impossibile . Alzi la mano, rimando ad Apple / Spotlight ...

mdfind 'kMDItemContentType=public.unix-executable'

Almeno funziona!


Buono a sapersi mdfindsu OSX. Notare che il nostro comando riporta gli eseguibili Unix per l' intero sistema . mdfind -onlyin . 'kMDItemContentType=public.unix-executable'limita i risultati alla sottostruttura della directory corrente. Punti di interesse minori: limitare la ricerca solo a una directory specifica (senza sottocartelle) apparentemente non è supportata. I collegamenti simbolici ai file eseguibili apparentemente non sono mai inclusi. Curiosamente, una volta mdfindtrovato un file eseguibile, la successiva rimozione del bit eseguibile non viene prelevato.
mklement0

Penso di aver trovato dei bug nel modo in cui Spotlight rileva / non rileva i file Unix eseguibili; Ho segnalato un bug con Apple e anche su openradar.me/20162683 . Incoraggio te, e chiunque altro sia interessato a questa funzionalità, a
segnalare

(Ci scusiamo per la raffica di commenti; si spera, ora hanno ragione) mdfind -onlyin . 'kMDItemContentType=public.unix-executable'si comporta come find . -type f -perm +111 -printfa. Cioè, trova i file con qualsiasi bit eseguibile impostato, che può produrre falsi positivi (anche se ciò potrebbe non essere un problema in pratica) - per trovare veramente solo i file eseguibili dall'utente corrente utilizzando BSD find, vedere la risposta di @ gniourf_gniourf. L'uso di una findsoluzione basata su ha il vantaggio di poter trovare anche collegamenti simbolici a file eseguibili, se lo si desidera (opzione -L), cosa che mdfindapparentemente non è possibile.
mklement0

1
@ mklement0 la mia risposta evitava gli abbellimenti - per cercare di inchiodare il punto a casa - ma sì, non useresti quasi mai questa forma "non guarnita". un'altra opzione - non sono sicuro che sia uscito - è il buon vecchio globbing .. ls /Applications/**/*(*)nel tuo (mio?) zshguscio
Alex Gray

Grazie per il zshsuggerimento utile - non lo sapevo; (sembra che si può o abbinare eseguibili ( *) o collegamenti simbolici ( @), ma non entrambi, giusto?). Per quanto riguarda il tuo punto originale: lasciatemi ribadire: find . -type f -perm +a=xfarà ciò che fa il tuo mdfindcomando, fornendo al contempo maggiore flessibilità. Puoi persino riformularlo per essere conforme a POSIX.
mklement0

1

Ebbene, la risposta più semplice sarebbe: "i tuoi file eseguibili sono nelle directory contenute nella tua variabile PATH" ma questo non troverebbe realmente i tuoi eseguibili e potrebbe comunque perdere molti eseguibili.

Non so molto di Mac ma penso che "mdfind 'kMDItemContentType = public.unix-executable'" potrebbe perdere cose come gli script interpretati

Se va bene per te trovare file con i bit eseguibili impostati (indipendentemente dal fatto che siano effettivamente eseguibili), allora va bene farlo

find . -type f -perm +111 -print

dove supportata, l'opzione "-executable" creerà un ulteriore filtro guardando acl e altri artefatti dei permessi, ma tecnicamente non è molto diverso da "-pemr +111".

Forse in futuro find supporterà "-magic" e ti permetterà di cercare esplicitamente file con uno specifico magic id ... ma poi dovresti specificare di definire tutti i formati eseguibili magic id.

Non sono a conoscenza di una facile uscita tecnicamente corretta su Unix.


1

Quindi, se in realtà vuoi trovare tipi di file eseguibili (ad esempio script, file binari ELF ecc. Ecc.) Non solo file con il permesso di esecuzione, allora probabilmente vorrai fare qualcosa di più simile a questo (dove la directory corrente. Può essere sostituita con qualsiasi cosa directory che desideri):

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

O per quelli di voi che non usano macports (utenti linux) o hanno altrimenti installato gnu find come find desiderato:

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

Sebbene se sei su OS X viene fornito con una piccola utility nascosta da qualche parte chiamata is_exec che fondamentalmente raggruppa quel piccolo test per te in modo da poter abbreviare la riga di comando se la trovi. Ma in questo modo è più flessibile in quanto puoi facilmente sostituire il test == con il test = ~ e usarlo per verificare proprietà più complesse come file di testo semplice eseguibili o qualsiasi altra informazione restituita dal comando file.


Le regole esatte per la citazione qui sono piuttosto opache, quindi finisco per elaborarlo per tentativi ed errori, ma mi piacerebbe sentire la spiegazione giusta.


0

Ho avuto lo stesso problema e la risposta era nel codice sorgente di dmenu : l'utilità più semplice creata per quello scopo. Puoi compilare i file "stest.c" e "arg.h" e dovrebbe funzionare. C'è una pagina man per l'utilizzo, che ho inserito per comodità:

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.