Listar todos los binarios de $ PATH

Respuestas:

38

Esta no es una respuesta, pero muestra binario, un comando que puede ejecutar

compgen -c

(asumiendo bash)

Otros comandos útiles

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.
Rahul Patil
fuente
1
Es bueno saber este comando, y realmente necesito ejecutables para completar. Tal vez use este comando en su lugar.
jcubic
Tenga en cuenta que también incluye funciones integradas, funciones, palabras clave (como in, {...) y alias.
Stéphane Chazelas
Señor, he actualizado ... Lo había guardado en mi borrador, hace mucho tiempo que encontré en este sitio ...
Rahul Patil
@jcubic, los shells ya lo hacen para completar el comando ¿Por qué hacerlo a mano?
vonbrand
@vonbrand Estoy trabajando en el shell en javascript / php y estoy ejecutando el shell en modo no interactivo.
jcubic
15

Con zsh:

whence -pm '*'

O:

print -rl -- $commands

(tenga en cuenta que para los comandos que aparecen en más de un componente de $PATH, solo enumerarán el primero).

Si desea los comandos sin las rutas completas, y ordenados por si acaso:

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

(es decir, obtenga las claves de esa matriz asociativa en lugar de los valores).

Stéphane Chazelas
fuente
No mencioné que estoy usando bash.
jcubic
5

En cualquier shell POSIX, sin utilizar ningún comando externo (suponiendo que printfestá integrado, si no se recurre a él echo), excepto para la clasificación final, y suponiendo que ningún nombre ejecutable contenga una nueva línea:

{ 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

Si no tiene ningún componente vacío en $PATH(use .en su lugar) ni componentes que comiencen -, ni caracteres comodín \[?*en componentes de RUTA o nombres ejecutables, y no hay ejecutables que comiencen con ., puede simplificar esto para:

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

Usando POSIX findy sed:

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

Si está dispuesto a enumerar el raro archivo no ejecutable o el archivo no regular en la ruta, hay una manera mucho más simple:

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

Esto omite los archivos de puntos; si los necesita, agregue la -Abandera lssi la tiene, o si desea adherirse a POSIX:ls -aH $PATH | grep -Fxv -e . -e ..

Hay soluciones más simples en bash y en zsh .

Gilles 'SO- deja de ser malvado'
fuente
Eso supone que $PATHestá configurado y no contiene componentes vacíos, y que los componentes no parecen encontrar predicados (u opciones ls). Algunos de ellos también ignorarán los archivos de puntos.
Stéphane Chazelas
@StephaneChazelas Sí, está bien. Además de los componentes vacíos, esto se incluye directamente en la categoría "no haga esto": PATH está bajo su control.
Gilles 'SO- deja de ser malvado'
Todavía no funciona si el elemento vacío es el último (como suele ser). (excepto en yashy zshen emulación sh).
Stéphane Chazelas
En su finduno. -pruneevitará la inclusión de directorios. Probablemente desee en -Llugar de -Hincluir enlaces simbólicos (comunes para los ejecutables). -perm -100no garantiza que el archivo sea ejecutable por usted (y podría (improbable) excluir archivos ejecutables).
Stéphane Chazelas
4

Se me ocurrió esto:

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

EDITAR : Parece que este es el único comando que no activa la alerta SELinux mientras lee algunos de los archivos en el directorio bin por el usuario de apache.

jcubic
fuente
55
¿Por qué el for? IFS=:; find $PATH -maxdepth 1 -executable -type f -printf '%f\n'
manatwork
@manatwork ¿funcionará para rutas no existentes?
jcubic
@manatwork no sabía que puedes hacer eso. Necesito leer más sobre IFS.
jcubic
3
Eso supone que $PATHestá configurado y no contiene caracteres comodín y no contiene componentes vacíos. Eso también supone la implementación de GNU de find.
Stéphane Chazelas
2
Debido a que en -type flugar de (GNU específico) -xtype f, eso también omitirá enlaces simbólicos. Eso tampoco enumerará el contenido de $PATHcomponentes que son enlaces simbólicos.
Stéphane Chazelas
3

Qué tal esto

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

La sustitución de cadena se usa con Bash.


fuente
3
Eso supone que $PATHestá configurado, no contiene caracteres comodín o en blanco, no contiene componentes vacíos. Eso supone que GNU encuentra también. Tenga en cuenta que ${var//x/y}es la kshsintaxis (también compatible con zsh y bash). Estrictamente hablando, eso también supone que los componentes $ PATH tampoco son findpredicados.
Stéphane Chazelas
1
Eso también supone que los $PATHcomponentes no son enlaces simbólicos.
Stéphane Chazelas
@StephaneChazelas: ¡Gracias! En otras palabras, caso habitual.
La configuración IFS=:es más robusta que hacer esta sustitución. Las rutas con espacios no son tan infrecuentes en Windows. Los enlaces simbólicos son bastante comunes, pero eso se resuelve fácilmente con -H.
Gilles 'SO- deja de ser malo'
@Gilles: por supuesto. Sin embargo, no veo ningún caso de uso razonable para esta pregunta, por lo tanto, no es necesaria una respuesta a prueba de balas.
1

Si puede ejecutar Python en su shell, también se puede usar el siguiente (ridículamente largo) de una sola línea:

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)) ])'

Este fue principalmente un ejercicio divertido para mí mismo para ver si se podía hacer usando una línea de código de Python sin recurrir al uso de la función 'exec'. En una forma más legible, y con algunos comentarios, el código se ve así:

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)) ])
brm
fuente
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
Steven
fuente