Список всех двоичных файлов из $ PATH


31

Есть ли одна строка, которая будет перечислять все исполняемые файлы из $ 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
Хорошо знать эту команду, и мне действительно нужны исполняемые файлы для завершения. Может быть, я использую эту команду вместо этого.
'18

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

Сэр, я обновил .. Я сохранил в своем черновике, давно я нашел на этом сайте ..
Рахул Патил

@jcubic, оболочки уже делают это для завершения команды. Почему это делается вручную?
vonbrand

@vonbrand Я работаю над оболочкой в ​​javascript / php и запускаю оболочку в неинтерактивном режиме.
jcubic

15

С зш:

whence -pm '*'

Или:

print -rl -- $commands

(обратите внимание, что для команд, которые появляются в более чем одном компоненте $PATH, они будут перечислять только первый).

Если вы хотите, чтобы команды без полных путей и сортировались для хорошей меры:

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

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


Я не упомянул, что использую bash.
Июнь

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в эмуляции sh).
Стефан Шазелас

В твоем 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

РЕДАКТИРОВАТЬ : Кажется, что это единственная команда, которая не вызывает предупреждение SELinux при чтении некоторых файлов в каталоге bin пользователем apache.


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

@manatwork будет работать для несуществующих путей?
jcubic

@manatwork не знал, что ты можешь сделать это. нужно читать больше об IFS.
14:10

3
Это предполагает, что $PATHэто установлено и не содержит подстановочных знаков и не содержит пустых компонентов. Это также предполагает реализацию GNU find.
Стефан Шазелас

2
Поскольку -type fвместо (специфичного для GNU) -xtype f, это также пропустит символические ссылки. Это также не будет перечислять содержимое $PATHкомпонентов, которые являются символическими ссылками.
Стефан Шазелас

3

Как насчет этого

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

Подстановка строк используется с Bash.


3
Это предполагает, что $PATHустановлено, не содержит подстановочных или пустых символов, не содержит пустых компонентов. Это предполагает и GNU find. Обратите внимание, что ${var//x/y}это kshсинтаксис (также поддерживается zsh и bash). Строго говоря, это также предполагает, что компоненты $ PATH также не являются findпредикатами.
Стефан Шазелас

1
Это также предполагает, что $PATHкомпоненты не являются символическими ссылками.
Стефан Шазелас

@StephaneChazelas: Спасибо! Другими словами, обычный случай.

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

@ Жиль: конечно. однако я не вижу разумного варианта использования этого вопроса, поэтому нет необходимости в пуленепробиваемом ответе.

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.