Elenca tutti i file / binari nel PERCORSO corrente


10

Esiste un modo "semplice" per eseguire un comando di stile "ls -la" per elencare tutti i file / binari eseguibili nel PERCORSO corrente?

(Ho intenzione di reindirizzare l'output in grep, per cercare comandi con prefissi sconosciuti ma fondamentalmente noti "nomi", il tipo di caso in cui il completamento automatico / tabulazione in bash è essenzialmente inutile. Quindi una sorta di "auto inverso funzione completa "...)


Puoi fare degli esempi? Come sarà diverso con ls -la?
John Siu,

"ls -la" / "ls -a" elenca solo i file nella directory corrente (pwd). Voglio elencare tutti i file (eseguibili) in tutte le directory incluse nel PERCORSO.
sme

Risposte:


19
compgen -c # will list all the commands you could run.
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. 

Bello, è proprio quello che stavo cercando. Include anche i file binari eseguibili nella directory corrente. Grazie.
sme

Funziona bene ... in bash.
Emanuel Berg,

c'è un modo per elencare il percorso di ognuno di questi senza farlo which $(compgen -A function -abck)?
h3rrmiller,

Non sono riuscito a trovare un'alternativa migliore.
Nykakin,

3

Ecco una funzione che elenca il contenuto delle directory $PATH. Se vengono passati argomenti, la funzione elenca solo i comandi il cui nome contiene uno degli argomenti. Gli argomenti sono interpretati come modelli glob.

shopt -s extglob
lspath () {
  local IFS pattern
  IFS='|'
  pattern="*@($*)*"
  IFS=':'
  for d in $PATH; do
    for x in "$d/"$pattern; do
      [ "$x" = "$d/$pattern" ] || echo "${x##*/}"
    done
  done | sort -u
}

Come molte cose, questo è più facile in zsh.

lspath () {
  (($#)) || set ''
  print -lr -- $^path/*$^@*(N:t) | sort -u
}

Il ^carattere nell'espansione dei parametri fa sì che il testo concatenato con l'array venga aggiunto a ciascun elemento dell'array, ad es . path=(/bin /usr/bin); echo $^path/fooStampe /bin/foo /usr/bin/foo.
/*$^@*sembra un insulto a fumetti ma in realtà è il carattere ordinario /, il carattere jolly *, il parametro speciale $@(l'array del parametro posizionale) con il ^modificatore e di nuovo *.
(N:t)è il qualificatore glob N per ottenere un'espansione vuota se non vi è alcuna corrispondenza seguita dal modificatore della cronologiat per mantenere solo il nome di base ("coda") di ogni corrispondenza.

Più criptico, evita la chiamata esterna ma questo è solo di interesse estetico:

lspath () {
  (($#)) || set ''
  local names; names=($^path/*$^@*(N:t))
  print -lr -- ${(ou)names}
}

Potresti infatti cercare il aproposcomando, che cerca le pagine man dei comandi la cui breve descrizione contiene una parola chiave. Una limitazione è che questo trova solo i comandi che hanno una pagina man.


Nella funzione zsh, il secondo ^sembra non produrre alcun output per una chiamata "nessun argomento"? Se lo lasci cadere, potresti elencarli tutti e cercare comunque singole parole chiave (ma non un elenco di esse). La (Non:t)sembra dire che asterischi devono essere ampliati? Non riuscivo a capire l'ultimo.
Emanuel Berg,

@EmanuelBerg Giusto, grazie per la correzione. Ho aggiunto una spiegazione del rumore di linea.
Gilles 'SO- smetti di essere malvagio' il

OK, vediamo: se non ci sono argomenti, li metti su niente, perché cosa c'era (quando non ce n'era), in qualche modo era ancora dirompente per quello che hai fatto dopo? Inoltre, non ho mai visto lettere minuscole path, ma quando lo eseguo nella shell, è effettivamente $ PATH ma con spazi anziché :. Il resto è cristallino :)
Emanuel Berg,

@EmanuelBerg No: se non ci sono argomenti, ho impostato la matrice di argomenti su una matrice a un elemento contenente la stringa vuota. In questo modo, nessun argomento significa che ogni nome che contiene le stringhe vuote corrisponde, ovvero ogni nome corrisponde. $pathè una funzione zsh: è un parametro legato , un array che viene aggiornato automaticamente quando PATHviene aggiornato e viceversa.
Gilles 'SO- smetti di essere malvagio' l'

Ah, ora vedo! Wow, non era ortodosso!
Emanuel Berg,

1
function findinpath () { 
   OLDIFS="$IFS" ; 
   IFS="$(printf ':\t\n')" ; 
   for regexp in "$@" ; do 
      for adir in $PATH ; do 
         find "$adir" -perm -111 -a ! -type d -ls 2>/dev/null | grep -i "/[^/]*$regexp"
      done ; 
   done ; 
   IFS="$OLDIFS" ; 
}

la ricerca corrisponde solo a: avere almeno un bit "x" (eseguibile) impostato e che non è una directory.

e usalo con un elenco di regexp da trovare:

findinpath awk sed '\.sh$'

regexp "." ti mostrerà tutto
Olivier Dulac il

con il normale IFS, puoi trovare voci duplicate nel tuo $ PATH con:echo $PATH | tr ':' '\n' | sort | uniq -d
Olivier Dulac

1
Ho provato il codice per tutte le risposte e questo è l'unico che in realtà mi ha dato quello che stavo cercando (percorsi completi per ogni istanza di un dato comando sul PERCORSO).
Chris Page

Sono contento che abbia aiutato :)
Olivier Dulac il

1
for i in $(echo $PATH | sed -e 's/\:/\ /g'); do find "$i" -perm +rwx -exec echo {} \; 2> /dev/null; done

prima facciamo eco $PATHin sed e sostituiamo ":" con "".

quindi facciamo una ricerca su ognuna di queste cose per trovare i file con rwx e farli eco.

2> /dev/nullè così findnon stampa errori


3
hai bisogno di un -maxdepth 1e -type fnella tua ricerca, altrimenti troverai le sottodirectory e i loro file (che la ricerca PATH non farà). Inoltre, il tuo test di autorizzazione è strano: dovrei +x, penserei?
derobert,

Questo non gestirà i casi limite se una voce vuota valida è la stessa di '.', Per esempio :/bino /bin::/usr/bin. Prova ad aggiungere s/::/:.:/;s/^:/.:/;s/:$/:./al sedcomando.
Arcege,

In realtà findpuoi cercare più percorsi, quindi puoi farlo senza il ciclo: find $(echo $PATH | sed -e 's/\:/\ /g') -perm +rwx …ovviamente, i nomi di directory contenenti spazi lo rovineranno, ma quello basato sul ciclo ha lo stesso problema comunque.
arte

@manatwork hai ragione. Ho aggiunto citazioni per risolvere il problema proprio ora
h3rrmiller,

Spiacente, questo non risolve nulla. Il problema è con la sostituzione dei due punti con spazi per consentire la divisione delle parole. Quindi trasformi “/ foo bar: / fiz baz” in “/ foo bar / fiz baz” e poi lo passi a for. Quindi forpasserà sopra un elenco di 4 parole. Per manipolare la suddivisione in parole meglio impostare la IFSbase alle vostre necessità: IFS=':'; find $PATH -perm +rwx ….
arte
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.