Câu trả lời:
Đây không phải là một câu trả lời, nhưng nó hiển thị nhị phân, một lệnh mà bạn có thể chạy
compgen -c
(giả sử bash
)
Các lệnh hữu ích khác
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
, {
...) và bí danh.
Với zsh:
whence -pm '*'
Hoặc là:
print -rl -- $commands
(lưu ý rằng đối với các lệnh xuất hiện trong nhiều thành phần $PATH
, chúng sẽ chỉ liệt kê phần đầu tiên).
Nếu bạn muốn các lệnh không có đường dẫn đầy đủ và được sắp xếp theo số đo tốt:
print -rl -- ${(ko)commands}
(nghĩa là lấy các khóa của mảng kết hợp đó thay vì các giá trị).
Trong bất kỳ shell POSIX nào, không sử dụng bất kỳ lệnh bên ngoài nào (giả sử đã printf
được tích hợp sẵn, nếu không rơi trở lại echo
) ngoại trừ việc sắp xếp cuối cùng và giả sử rằng không có tên thực thi nào có chứa một dòng mới:
{ 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
Nếu bạn không có thành phần trống trong $PATH
(sử dụng .
thay thế) cũng như các thành phần bắt đầu bằng -
, cũng không phải ký tự đại diện \[?*
trong các thành phần PATH hoặc tên thực thi và không có tệp thực thi nào bắt đầu bằng .
, bạn có thể đơn giản hóa điều này thành:
{ IFS=:; for d in $PATH; do for f in $d/*; do [ -f $f ] && [ -x $f ] && echo ${x##*/}; done; done; } | sort
Sử dụng POSIX find
và sed
:
{ IFS=:; set -f; find -H $PATH -prune -type f -perm -100 -print; } | sed 's!.*/!!' | sort
Nếu bạn sẵn sàng liệt kê tệp không thể thực thi hiếm hoặc tệp không thường xuyên trong đường dẫn, có một cách đơn giản hơn nhiều:
{ IFS=:; ls -H $PATH; } | sort
Điều này bỏ qua các tập tin dấu chấm; nếu bạn cần chúng, hãy thêm -A
cờ vào ls
nếu bạn có nó hoặc nếu bạn muốn gắn bó với POSIX:ls -aH $PATH | grep -Fxv -e . -e ..
Có các giải pháp đơn giản hơn trong bash và trong zsh .
$PATH
được đặt và không chứa các thành phần trống và các thành phần đó trông không giống như tìm các vị từ (hoặc tùy chọn ls). Một số trong số đó cũng sẽ bỏ qua các tập tin dấu chấm.
yash
và zsh
trong thi đua sh).
find
một của bạn . -prune
sẽ ngăn chặn danh sách thư mục. Bạn có thể muốn -L
thay vì -H
như bạn muốn bao gồm các liên kết tượng trưng (phổ biến cho các tệp thực thi). -perm -100
không đảm bảo rằng tệp có thể được thực thi bởi bạn (và có thể (không thể) loại trừ các tệp thực thi).
Tôi nghĩ ra cái này:
IFS=':';for i in $PATH; do test -d "$i" && find "$i" -maxdepth 1 -executable -type f -exec basename {} \;; done
EDIT : Có vẻ như đây là lệnh duy nhất không kích hoạt cảnh báo SELinux trong khi đọc một số tệp trong thư mục bin của người dùng apache.
for
? IFS=:; find $PATH -maxdepth 1 -executable -type f -printf '%f\n'
$PATH
được đặt và không chứa các ký tự đại diện và không chứa các thành phần trống. Điều đó cũng giả định việc thực hiện GNU find
.
-type f
thay vì (GNU cụ thể) -xtype f
, điều đó cũng sẽ bỏ qua các liên kết tượng trưng. Điều đó cũng sẽ không liệt kê nội dung của các $PATH
thành phần là liên kết tượng trưng.
Còn cái này thì sao
find ${PATH//:/ } -maxdepth 1 -executable
Sự thay thế chuỗi được sử dụng với Bash.
$PATH
được đặt, không chứa ký tự đại diện hoặc ký tự trống, không chứa các thành phần trống. Điều đó giả định GNU cũng tìm thấy. Lưu ý đó ${var//x/y}
là ksh
cú pháp (cũng được hỗ trợ bởi zsh và bash). Nói đúng ra cũng cho rằng các thành phần $ PATH cũng không phải là find
vị ngữ.
$PATH
các thành phần không phải là liên kết tượng trưng.
IFS=:
mạnh mẽ hơn so với thực hiện thay thế này. Đường dẫn có dấu cách không phổ biến trên Windows. Liên kết tượng trưng là khá phổ biến, nhưng điều đó dễ dàng được giải quyết -H
.
Nếu bạn có thể chạy python trong shell của mình, thì một lớp lót sau (dài một cách lố bịch) cũng có thể được sử dụng:
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)) ])'
Đây chủ yếu là một bài tập thú vị cho bản thân tôi để xem liệu nó có thể được thực hiện bằng cách sử dụng một dòng mã trăn mà không cần sử dụng chức năng 'exec' hay không. Ở dạng dễ đọc hơn và với một số bình luận, mã trông như thế này:
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