แสดงรายการไบนารีทั้งหมดจาก $ PATH


คำตอบ:


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

โปรดทราบว่ามันยังมี builtins, ฟังก์ชั่น, คำหลัก (เช่นin, {... ) และชื่อแทน
Stéphane Chazelas

ท่านครับฉันได้อัพเดท .. ฉันได้บันทึกไว้ในร่างของฉันเมื่อนานมาแล้วฉันพบในเว็บไซต์นี้ ..
Rahul Patil

@jcubic เชลล์ทำไปแล้วสำหรับการทำคำสั่งให้สมบูรณ์ทำไมต้องทำด้วยมือ
vonbrand

@ vonbrand ฉันกำลังทำงานกับเชลล์ใน javascript / php และฉันกำลังใช้งานเชลล์ในโหมดที่ไม่โต้ตอบ
jcubic

14

ด้วย zsh:

whence -pm '*'

หรือ:

print -rl -- $commands

(โปรดทราบว่าสำหรับคำสั่งที่ปรากฏในองค์ประกอบมากกว่าหนึ่ง$PATHรายการคำสั่งนั้นจะแสดงเพียงรายการแรกเท่านั้น)

หากคุณต้องการคำสั่งที่ไม่มีพา ธ เต็มและเรียงลำดับได้ดี:

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

(นั่นคือรับคีย์ของอาร์เรย์ที่เชื่อมโยงนั้นแทนค่า)


ฉันไม่ได้พูดถึงว่าฉันใช้ทุบตี
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

ข้ามไฟล์ dot หากคุณต้องการให้เพิ่มการ-Aตั้งค่าสถานะlsหากคุณมีหรือตั้งค่า POSIX:ls -aH $PATH | grep -Fxv -e . -e ..

มีโซลูชั่นที่เรียบง่ายอยู่ในทุบตีและใน zsh


ที่ถือว่า$PATHมีการตั้งค่าและไม่มีส่วนประกอบที่ว่างเปล่าและส่วนประกอบนั้นดูไม่เหมือนหาภาคแสดง (หรือตัวเลือก ls) บางคนก็จะไม่สนใจไฟล์จุด
Stéphane Chazelas

@StephaneChazelas ใช่แล้ว นอกเหนือจากส่วนประกอบที่ว่างเปล่าสิ่งนี้อยู่ภายใต้หมวดหมู่“ ไม่ทำเช่นนี้” อย่างครบถ้วน - PATH อยู่ภายใต้การควบคุมของคุณ
Gilles 'หยุดความชั่วร้าย'

มันยังคงไม่ทำงานหากองค์ประกอบที่ว่างเปล่ามีอายุการใช้งาน (ตามปกติ) (ยกเว้นในyashและzshในการจำลอง SH)
Stéphane Chazelas

ในของคุณfindหนึ่ง -pruneจะป้องกันรายการไดเรกทอรี คุณอาจต้องการ-Lแทนที่จะ-Hเป็นตามที่คุณต้องการรวม symlinks (ทั่วไปสำหรับ executables) -perm -100ไม่รับประกันว่าไฟล์นั้นจะสามารถเรียกใช้งานได้โดยคุณ (และอาจ (ไม่น่าจะ) ยกเว้นไฟล์ที่สามารถเรียกใช้งานได้
Stéphane Chazelas

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

@ การผลิตไม่ทราบว่าคุณสามารถทำได้ ต้องอ่านเพิ่มเติมเกี่ยวกับ IFS
jcubic

3
ที่ถือว่า$PATHมีการตั้งค่าและไม่มีอักขระตัวแทนและไม่มีส่วนประกอบว่างเปล่า findที่ยังถือว่าการดำเนินงานของกนู
Stéphane Chazelas

2
เพราะ-type fแทนที่จะเป็น (เฉพาะ GNU) -xtype fนั่นก็จะละเว้น symlink ที่จะไม่แสดงรายการเนื้อหาของ$PATHส่วนประกอบที่ symlink
Stéphane Chazelas

3

เกี่ยวกับเรื่องนี้

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

การแทนที่สตริงใช้กับ Bash


3
ที่ถือว่า$PATHมีการตั้งค่าไม่มีอักขระตัวแทนหรืออักขระว่างเปล่าไม่มีส่วนประกอบว่างเปล่า นั่นถือว่า GNU พบเช่นกัน โปรดทราบว่า${var//x/y}เป็นkshไวยากรณ์ (สนับสนุนโดย zsh และ bash) การพูดอย่างเคร่งครัดที่ยังถือว่าส่วนประกอบของ $ PATH นั้นไม่ได้findแสดงเพรดิเคตเช่นกัน
Stéphane Chazelas

1
ซึ่งยังถือว่า$PATHส่วนประกอบนั้นไม่ใช่ symlink
Stéphane Chazelas

@StephaneChazelas: ขอบคุณ! ในคำอื่น ๆ กรณีปกติ

การตั้งค่าIFS=:นั้นแข็งแกร่งกว่าการทดแทนสิ่งนี้ เส้นทางที่มีช่องว่างไม่ใช่เรื่องผิดปกติบน Windows การเชื่อมโยงสัญลักษณ์กันอย่างเป็นธรรม -Hแต่ที่แก้ไขได้อย่างง่ายดายด้วย
Gilles 'หยุดความชั่วร้าย'

@Gilles: แน่นอน แต่ฉันไม่เห็นกรณีการใช้งานที่สมเหตุสมผลสำหรับคำถามนี้ดังนั้นจึงไม่จำเป็นต้องมีคำตอบที่พิสูจน์ด้วยกระสุน

1

หากคุณสามารถเรียกใช้งานไพ ธ อนในเชลล์ของคุณสามารถใช้หนึ่งซับต่อไปนี้ (ยาวขัน):

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

นี่เป็นแบบฝึกหัดสนุก ๆ สำหรับตัวเองเพื่อดูว่าสามารถทำได้โดยใช้รหัสไพ ธ อนหนึ่งบรรทัดโดยไม่ต้องใช้ฟังก์ชัน '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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.