Список усіх бінарних файлів від $ PATH


30

Чи є один-лайнер, який буде перераховувати всі виконувані файли від $ PATH в bash.

Відповіді:


38

Це не відповідь, але вона показує двійкову, команду, яку можна було запустити

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.

1
Добре знати цю команду, і мені фактично потрібні виконувані файли для завершення. Можливо, я замість цього використовую цю команду.
jcubic

Зауважте, що він також включає вбудовані, функції, ключові слова (наприклад in, {...) та псевдоніми.
Стефан Шазелас

Сер, я оновив .. Я зберіг свою чернетку, давно я знайшов на цьому сайті ..
Рахул Патіль

@jcubic, оболонки вже роблять це для виконання команд Чому це робити вручну?
фонбранд

@vonbrand Я працюю над оболонкою в JavaScript / php і виконую оболонку в неінтерактивному режимі.
jcubic

15

З zsh:

whence -pm '*'

Або:

print -rl -- $commands

(зауважте, що для команд, що з'являються у більш ніж одному компоненті $PATH, вони перелічать лише першу).

Якщо ви хочете, щоб команди без повних шляхів були відсортовані:

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

(тобто отримайте ключі цього асоціативного масиву замість значень).


Я не згадував, що використовую bash.
jcubic

5

У будь-якій оболонці 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 ..

Є більш прості рішення в bash і в zsh .


Це передбачає, що $PATHвстановлено і не містить порожніх компонентів, а компоненти не схожі на пошук предикатів (або параметрів ls). Деякі з них також ігнорують файли крапок.
Стефан Шазелас

@StephaneChazelas Так, добре. Окрім порожніх компонентів, це прямо підпадає під категорію "не робіть цього" - PATH знаходиться під вашим контролем.
Жил "ТАК - перестань бути злим"

Він все ще не працює, якщо порожній елемент останній (як зазвичай). (за винятком емуляції yashі zshв ш).
Стефан Шазелас

У вашому find. -pruneне дозволить перерахувати каталоги. Ви, мабуть, хочете -Lзамість того, -Hяк хочете включити посилання (загальні для виконуваних файлів). -perm -100не дає гарантії, що файл, який ви виконуєте (і може (малоймовірно) виключати виконувані файли).
Стефан Шазелас

4

Я придумав це:

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

EDIT : Схоже, це єдина команда, яка не запускає SELinux-попередження під час читання деяких файлів у каталозі bin користувачем apache.


5
Чому for? IFS=:; find $PATH -maxdepth 1 -executable -type f -printf '%f\n'
манатура

@manatwork це буде працювати для неіснуючих шляхів?
jcubic

@manatwork не знав, що ти можеш це зробити. потрібно прочитати більше про IFS.
jcubic

3
Це передбачає, що $PATHвстановлено і не містить символів підстановки та не містить порожніх компонентів. Це також передбачає реалізацію GNU find.
Стефан Шазелас

2
Через те, що -type fзамість (специфічно для GNU) -xtype f, це також опускає символьні посилання. Це також не буде перелічити вміст $PATHкомпонентів, які є посиланнями.
Стефан Шазелас

3

Як щодо цього

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

Підстановка рядків використовується з Bash.


3
Це передбачає, що $PATHвстановлено, не містить символів підстановки чи порожніх символів, не містить порожніх компонентів. Це передбачає і пошук GNU. Зауважте, що ${var//x/y}це kshсинтаксис (також підтримується zsh та bash). Власне кажучи, це також передбачає, що компоненти $ PATH також не є findпредикатами.
Стефан Шазелас

1
Це також передбачає, що $PATHкомпоненти не є посиланнями.
Стефан Хазелас

@StephaneChazelas: Дякую! Іншими словами, звичайний випадок.

Налаштування IFS=:більш надійне, ніж робити цю заміну. Шлях із пробілами не є рідкістю для Windows. Символічні посилання досить поширені, але це легко вирішити -H.
Жил "ТАК - перестань бути злим"

@Gilles: звичайно. однак я не бачу жодного розумного корисного випадку для цього питання, тому немає необхідності у відповіді на кулі.

1

Якщо ви можете запустити 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)) ])

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.