Відповіді:
Це не відповідь, але вона показує двійкову, команду, яку можна було запустити
compgen -c
(припускаючи bash
)
Інші корисні команди
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.
in
, {
...) та псевдоніми.
З zsh:
whence -pm '*'
Або:
print -rl -- $commands
(зауважте, що для команд, що з'являються у більш ніж одному компоненті $PATH
, вони перелічать лише першу).
Якщо ви хочете, щоб команди без повних шляхів були відсортовані:
print -rl -- ${(ko)commands}
(тобто отримайте ключі цього асоціативного масиву замість значень).
У будь-якій оболонці POSIX, не використовуючи жодної зовнішньої команди (припускаючи, що printf
вона вбудована, якщо не повернеться до echo
), за винятком остаточного сортування, та припускаючи, що жодне виконуване ім’я не містить новий рядок:
{ 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
Якщо у вас немає пустого компонента $PATH
(використовуйте .
замість нього), ні компонентів, що починаються з -
, ні символів підстановки, \[?*
ні компонентів PATH, ні імен виконавців, і жодного виконуваного файлу .
, ви можете спростити це до:
{ IFS=:; for d in $PATH; do for f in $d/*; do [ -f $f ] && [ -x $f ] && echo ${x##*/}; done; done; } | sort
Використання POSIX find
та sed
:
{ IFS=:; set -f; find -H $PATH -prune -type f -perm -100 -print; } | sed 's!.*/!!' | sort
Якщо ви хочете перерахувати рідкісний не виконуваний файл або нерегулярний файл на шляху, є набагато простіший спосіб:
{ IFS=:; ls -H $PATH; } | sort
Це пропускає крапкові файли; якщо вони вам потрібні, додайте -A
прапор, ls
якщо у вас його є, або якщо ви хочете дотримуватися POSIX:ls -aH $PATH | grep -Fxv -e . -e ..
$PATH
встановлено і не містить порожніх компонентів, а компоненти не схожі на пошук предикатів (або параметрів ls). Деякі з них також ігнорують файли крапок.
yash
і zsh
в ш).
find
. -prune
не дозволить перерахувати каталоги. Ви, мабуть, хочете -L
замість того, -H
як хочете включити посилання (загальні для виконуваних файлів). -perm -100
не дає гарантії, що файл, який ви виконуєте (і може (малоймовірно) виключати виконувані файли).
Я придумав це:
IFS=':';for i in $PATH; do test -d "$i" && find "$i" -maxdepth 1 -executable -type f -exec basename {} \;; done
EDIT : Схоже, це єдина команда, яка не запускає SELinux-попередження під час читання деяких файлів у каталозі bin користувачем apache.
for
? IFS=:; find $PATH -maxdepth 1 -executable -type f -printf '%f\n'
$PATH
встановлено і не містить символів підстановки та не містить порожніх компонентів. Це також передбачає реалізацію GNU find
.
-type f
замість (специфічно для GNU) -xtype f
, це також опускає символьні посилання. Це також не буде перелічити вміст $PATH
компонентів, які є посиланнями.
Як щодо цього
find ${PATH//:/ } -maxdepth 1 -executable
Підстановка рядків використовується з Bash.
$PATH
встановлено, не містить символів підстановки чи порожніх символів, не містить порожніх компонентів. Це передбачає і пошук GNU. Зауважте, що ${var//x/y}
це ksh
синтаксис (також підтримується zsh та bash). Власне кажучи, це також передбачає, що компоненти $ PATH також не є find
предикатами.
$PATH
компоненти не є посиланнями.
IFS=:
більш надійне, ніж робити цю заміну. Шлях із пробілами не є рідкістю для Windows. Символічні посилання досить поширені, але це легко вирішити -H
.
Якщо ви можете запустити python у своїй оболонці, також можна використовувати наступний (смішно довгий) однолінійний:
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)) ])'
Це в основному було цікавою вправою для себе, щоб побачити, чи можна це зробити за допомогою одного рядка коду python, не вдаючись до використання функції «exec». У більш читаному вигляді та з деякими коментарями код виглядає так:
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)) ])
#!/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