Elenca tutti i file binari da $ PATH


Risposte:


38

Questa non è una risposta, ma mostra binario, un comando che potresti eseguire

compgen -c

(supponendo bash)

Altri comandi utili

compgen -a # will list all the aliases you could run.
compgen -b # will list all the built-ins you could run.
compgen -k # will list all the keywords you could run.
compgen -A function # will list all the functions you could run.
compgen -A function -abck # will list all the above in one go.

1
Buono a sapersi questo comando, e in realtà ho bisogno di eseguibili per il completamento. Forse invece uso questo comando.
jcubic,

Nota che include anche builtin, funzioni, parole chiave (come in, {...) e alias.
Stéphane Chazelas,

Signore, ho aggiornato .. Avevo salvato nella mia bozza, molto tempo fa ho trovato su questo sito ..
Rahul Patil

@jcubic, le shell lo fanno già per il completamento del comando Perché farlo a mano?
vonbrand,

@vonbrand Sto lavorando sulla shell in javascript / php e sto eseguendo la shell in modalità non interattiva.
jcubic,

15

Con zsh:

whence -pm '*'

O:

print -rl -- $commands

(nota che per i comandi che compaiono in più di un componente $PATH, elencheranno solo il primo).

Se vuoi i comandi senza i percorsi completi e ordinati per buona misura:

print -rl -- ${(ko)commands}

(ovvero, ottenere le chiavi di quell'array associativo anziché i valori).


Non ho detto che sto usando bash.
jcubic,

5

In qualsiasi shell POSIX, senza utilizzare alcun comando esterno (supponendo che printfsia incorporato, se non ricadere in echo), tranne per l'ordinamento finale e supponendo che nessun nome eseguibile contenga una nuova riga:

{ set -f; IFS=:; for d in $PATH; do set +f; [ -n "$d" ] || d=.; for f in "$d"/.[!.]* "$d"/..?* "$d"/*; do [ -f "$f" ] && [ -x "$f" ] && printf '%s\n' "${x##*/}"; done; done; } | sort

Se non si dispone di alcun componente vuoto in $PATH(utilizzare .invece) né componenti che iniziano con -, né caratteri jolly \[?*in componenti PATH o nomi di eseguibili e nessun eseguibile che inizia con ., è possibile semplificare questo per:

{ IFS=:; for d in $PATH; do for f in $d/*; do [ -f $f ] && [ -x $f ] && echo ${x##*/}; done; done; } | sort

Utilizzando POSIX finde sed:

{ IFS=:; set -f; find -H $PATH -prune -type f -perm -100 -print; } | sed 's!.*/!!' | sort

Se sei disposto a elencare il raro file non eseguibile o non regolare nel percorso, c'è un modo molto più semplice:

{ IFS=:; ls -H $PATH; } | sort

Questo salta i file punto; se ne hai bisogno, aggiungi la -Abandiera a lsse la tua ce l'ha, o se vuoi aderire a POSIX:ls -aH $PATH | grep -Fxv -e . -e ..

Ci sono soluzioni più semplici in bash e in zsh .


Ciò presuppone che $PATHsia impostato e che non contenga componenti vuoti e che i componenti non sembrano trovare predicati (o opzioni ls). Alcuni di questi ignoreranno anche i file di punti.
Stéphane Chazelas,

@StephaneChazelas Sì, ok. A parte i componenti vuoti, questo rientra esattamente nella categoria "non farlo" - PATH è sotto il tuo controllo.
Gilles 'SO- smetti di essere malvagio' il

Non funziona ancora se l'elemento vuoto è l'ultimo (come sempre). (eccetto in yashe zshin emulazione sh).
Stéphane Chazelas,

Nel tuo find. -pruneimpedirà di elencare le directory. Probabilmente -Linvece di -Hcome si desidera includere collegamenti simbolici (comune per gli eseguibili). -perm -100non garantisce che il file sia eseguibile da te (e potrebbe (improbabile) escludere i file eseguibili).
Stéphane Chazelas,

4

Ho pensato a questo:

IFS=':';for i in $PATH; do test -d "$i" && find "$i" -maxdepth 1 -executable -type f -exec basename {} \;; done

EDIT : Sembra che questo sia l'unico comando che non attiva l'avviso SELinux durante la lettura di alcuni file nella directory bin dall'utente apache.


5
Perché il for? IFS=:; find $PATH -maxdepth 1 -executable -type f -printf '%f\n'
arte

@manatwork funzionerà per percorsi inesistenti?
jcubic,

@manatwork non sapeva che puoi farlo. bisogno di leggere di più su IFS.
jcubic,

3
Ciò presuppone che $PATHsia impostato e non contenga caratteri jolly e non contenga componenti vuoti. Ciò presuppone anche l'implementazione GNU di find.
Stéphane Chazelas,

2
A causa di -type finvece di (specifico GNU) -xtype f, questo ometterà anche i collegamenti simbolici. Anche questo non elencherà il contenuto dei $PATHcomponenti che sono collegamenti simbolici.
Stéphane Chazelas,

3

Cosa ne pensi di questo

find ${PATH//:/ } -maxdepth 1 -executable

La sostituzione di stringa viene utilizzata con Bash.


3
Ciò presuppone che $PATHsia impostato, non contenga caratteri jolly o caratteri vuoti, non contenga componenti vuoti. Ciò presuppone che anche GNU lo trovi. Si noti che ${var//x/y}è la kshsintassi (supportata anche da zsh e bash). A rigor di termini, ciò presuppone anche che i componenti $ PATH non siano neanche findpredicati.
Stéphane Chazelas,

1
Ciò presuppone anche che i $PATHcomponenti non siano collegamenti simbolici.
Stéphane Chazelas,

@StephaneChazelas: Grazie! In altre parole, al solito caso.

L'impostazione IFS=:è più robusta rispetto a questa sostituzione. I percorsi con spazi non sono così rari su Windows. I collegamenti simbolici sono abbastanza comuni, ma è facilmente risolvibile -H.
Gilles 'SO-smetti di essere malvagio' il

@Gilles: certo. tuttavia non vedo alcun caso d'uso ragionevole per questa domanda, pertanto non è necessaria una risposta a prova di proiettile.

1

Se riesci a far funzionare Python nella tua shell, puoi usare anche la seguente linea (ridicolmente lunga):

python -c 'import os;import sys;output = lambda(x) : sys.stdout.write(x + "\n"); paths = os.environ["PATH"].split(":") ; listdir = lambda(p) : os.listdir(p) if os.path.isdir(p) else [ ] ; isfile = lambda(x) : True if os.path.isfile(os.path.join(x[0],x[1])) else False ; isexe = lambda(x) : True if os.access(os.path.join(x[0],x[1]), os.X_OK) else False ; map(output,[ os.path.join(p,f) for p in paths for f in listdir(p) if isfile((p,f)) and isexe((p,f)) ])'

Questo è stato per lo più un esercizio divertente per me stesso per vedere se si potesse fare usando una riga di codice Python senza ricorrere all'utilizzo della funzione 'exec'. In una forma più leggibile e con alcuni commenti, il codice è simile al seguente:

import os
import sys

# This is just to have a function to output something on the screen.
# I'm using python 2.7 in which 'print' is not a function and cannot
# be used in the 'map' function.
output = lambda(x) : sys.stdout.write(x + "\n")

# Get a list of the components in the PATH environment variable. Will
# abort the program is PATH doesn't exist
paths = os.environ["PATH"].split(":")

# os.listdir raises an error is something is not a path so I'm creating
# a small function that only executes it if 'p' is a directory
listdir = lambda(p) : os.listdir(p) if os.path.isdir(p) else [ ]

# Checks if the path specified by x[0] and x[1] is a file
isfile = lambda(x) : True if os.path.isfile(os.path.join(x[0],x[1])) else False

# Checks if the path specified by x[0] and x[1] has the executable flag set
isexe = lambda(x) : True if os.access(os.path.join(x[0],x[1]), os.X_OK) else False

# Here, I'm using a list comprehension to build a list of all executable files
# in the PATH, and abusing the map function to write every name in the resulting
# list to the screen.
map(output, [ os.path.join(p,f) for p in paths for f in listdir(p) if isfile((p,f)) and isexe((p,f)) ])

0
#!/usr/bin/env python
import os
from os.path import expanduser, isdir, join, pathsep

def list_executables():
    paths = os.environ["PATH"].split(pathsep)
    executables = []
    for path in filter(isdir, paths):
        for file_ in os.listdir(path):
            if os.access(join(path, file_), os.X_OK):
                executables.append(file_)
    return executables
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.