Liệt kê tất cả các tệp / tệp nhị phân trong PATH hiện tại


10

Có cách nào "dễ dàng" để chạy lệnh kiểu "ls -la" để liệt kê tất cả các tệp / tệp nhị phân thực thi trong PATH hiện tại không?

(Tôi dự định chuyển đầu ra thành grep, để tìm kiếm các lệnh có tiền tố không xác định nhưng về cơ bản là "tên", loại trường hợp khi tự động hoàn thành / tab trong bash về cơ bản là vô dụng. tính năng hoàn chỉnh "...)


Bạn có thể cho ví dụ? Nó sẽ khác với ls -lanhư thế nào?
John Siu

"ls -la" / "ls -a" chỉ liệt kê các tệp trong thư mục hiện tại của bạn (pwd). Tôi muốn liệt kê tất cả các tệp (thực thi) trong tất cả các thư mục có trong PATH.
sme

Câu trả lời:


19
compgen -c # will list all the commands you could run.
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. 

Đẹp, đây là rất nhiều những gì tôi đã tìm kiếm. Nó thậm chí bao gồm các nhị phân thực thi trong thư mục hiện tại. Cảm ơn.
sme

Hoạt động tốt ... trong bash.
Emanuel Berg

Có cách nào để liệt kê đường dẫn của mỗi thứ này mà không làm gì which $(compgen -A function -abck)không?
h3rrmiller

Tôi không thể tìm thấy bất kỳ thay thế tốt hơn.
Nykakin

3

Đây là một chức năng liệt kê nội dung của các thư mục $PATH. Nếu thông qua các đối số, hàm chỉ liệt kê các lệnh có tên liên quan đến một trong các đối số. Các đối số được hiểu là mô hình toàn cầu.

shopt -s extglob
lspath () {
  local IFS pattern
  IFS='|'
  pattern="*@($*)*"
  IFS=':'
  for d in $PATH; do
    for x in "$d/"$pattern; do
      [ "$x" = "$d/$pattern" ] || echo "${x##*/}"
    done
  done | sort -u
}

Giống như nhiều thứ, điều này là dễ dàng hơn trong zsh.

lspath () {
  (($#)) || set ''
  print -lr -- $^path/*$^@*(N:t) | sort -u
}

^tự trong mở rộng tham số làm cho văn bản được nối với mảng được thêm vào từng thành phần mảng, ví dụ như path=(/bin /usr/bin); echo $^path/fooin /bin/foo /usr/bin/foo.
/*$^@*trông giống như một sự xúc phạm trong truyện tranh nhưng thực tế là nhân vật bình thường /, ký tự đại diện *, tham số đặc biệt $@(mảng tham số vị trí) với công cụ ^sửa đổi, và một lần nữa *.
(N:t)vòng loại toàn cầu N để có được một bản mở rộng trống nếu không có kết quả trùng khớp theo sau bởi công cụ sửa đổi lịch sử t để chỉ giữ lại tên cơ sở (Đuôi đuôi) của mỗi trận đấu.

Khó hiểu hơn, tránh cuộc gọi bên ngoài nhưng đây chỉ là mối quan tâm của mỹ phẩm:

lspath () {
  (($#)) || set ''
  local names; names=($^path/*$^@*(N:t))
  print -lr -- ${(ou)names}
}

Trong thực tế, bạn có thể đang tìm kiếm aproposlệnh tìm kiếm các trang man của các lệnh có mô tả ngắn chứa từ khóa. Một hạn chế là điều này chỉ tìm thấy các lệnh có trang man.


Trong chức năng zsh, thứ hai ^dường như dẫn đến không có đầu ra cho một "không có đối số" cuộc gọi? Nếu bạn bỏ nó, bạn có thể liệt kê tất cả, và vẫn tìm kiếm các từ khóa duy nhất (nhưng không phải là danh sách của chúng). Các (Non:t)dường như để nói rằng dấu hoa thị cần được mở rộng? Không thể tìm ra cái cuối cùng.
Emanuel Berg

@EmanuelBerg Phải, cảm ơn vì đã sửa. Tôi đã thêm một lời giải thích về tiếng ồn dòng.
Gilles 'SO- ngừng trở nên xấu xa'

OK, hãy xem: Nếu không có đối số, bạn đặt "chúng" thành không có gì, bởi vì những gì ở đó (khi không có), vẫn bằng cách nào đó làm gián đoạn những gì bạn đã làm tiếp theo? Ngoài ra, tôi chưa bao giờ thấy chữ thường path, nhưng khi tôi chạy nó trong vỏ, nó thực sự là $ PATH nhưng có khoảng trắng thay vì :. Phần còn lại rất rõ ràng :)
Emanuel Berg

@EmanuelBerg Không: nếu không có đối số, tôi đặt mảng đối số là mảng một phần tử có chứa chuỗi rỗng. Theo cách này, không có đối số có nghĩa là mọi tên chứa chuỗi rỗng khớp, tức là mọi tên đều khớp. $pathlà một tính năng zsh: đó là một tham số gắn liền , một mảng được tự động cập nhật khi PATHđược cập nhật và ngược lại.
Gilles 'SO- ngừng trở nên xấu xa'

Aha, giờ thì tôi đã thấy! Wow, đó là không chính thống!
Emanuel Berg

1
function findinpath () { 
   OLDIFS="$IFS" ; 
   IFS="$(printf ':\t\n')" ; 
   for regexp in "$@" ; do 
      for adir in $PATH ; do 
         find "$adir" -perm -111 -a ! -type d -ls 2>/dev/null | grep -i "/[^/]*$regexp"
      done ; 
   done ; 
   IFS="$OLDIFS" ; 
}

Tìm kiếm chỉ khớp với: có ít nhất một bit "x" (có thể thực thi) và đó không phải là một thư mục.

và sử dụng nó với một danh sách regrec được tìm thấy:

findinpath awk sed '\.sh$'

regrec "." sẽ cho bạn thấy tất cả mọi thứ
Olivier Dulac

với IFS thông thường, bạn có thể tìm thấy các mục trùng lặp trong $ PATH của mình với:echo $PATH | tr ':' '\n' | sort | uniq -d
Olivier Dulac

1
Tôi đã thử mã cho tất cả các câu trả lời và đây là câu duy nhất thực sự mang lại cho tôi thứ mà tôi đang tìm kiếm (đường dẫn đầy đủ đến mọi phiên bản của một lệnh đã cho trên PATH).
Chris Trang

Tôi rất vui vì nó đã giúp :)
Olivier Dulac

1
for i in $(echo $PATH | sed -e 's/\:/\ /g'); do find "$i" -perm +rwx -exec echo {} \; 2> /dev/null; done

đầu tiên chúng tôi lặp lại $PATHvào sed và thay thế ":" bằng "".

sau đó chúng tôi tìm một trong những điều đó để tìm các tệp có rwx và lặp lại chúng.

2> /dev/nullnhư vậy findsẽ không in lỗi


3
bạn cần một -maxdepth 1-type ftrong tìm kiếm của bạn, nếu không bạn sẽ tìm thấy các thư mục con và các tệp của chúng (mà tìm kiếm PATH sẽ không). Ngoài ra, bài kiểm tra cấp phép của bạn là kỳ lạ nên chỉ dành cho +x, tôi nghĩ sao?
derobert

Điều này sẽ không xử lý các trường hợp cạnh là một mục trống hợp lệ giống như '.', Ví dụ :/binhoặc /bin::/usr/bin. Hãy thử thêm s/::/:.:/;s/^:/.:/;s/:$/:./vào sedlệnh.
Bắt đầu

Trên thực tế findcó thể tìm kiếm nhiều đường dẫn hơn, vì vậy bạn có thể thực hiện mà không cần vòng lặp: find $(echo $PATH | sed -e 's/\:/\ /g') -perm +rwx …Tất nhiên, tên thư mục chứa khoảng trắng sẽ làm rối tung nó, nhưng dù sao vòng lặp cũng có cùng một vấn đề.
manatwork

@manatwork bạn nói đúng. Tôi đã thêm các trích dẫn để giải quyết vấn đề đó ngay bây giờ
h3rrmiller

Xin lỗi, điều đó không giải quyết được gì. Vấn đề là với việc thay thế dấu hai chấm bằng dấu cách để cho phép chia từ. Vì vậy, bạn chuyển đổi thanh / foo thanh: / fiz baz phạm thành thanh / foo thanh / fiz baz 'sau đó chuyển nó sang for. Vì vậy, forsẽ lặp qua một danh sách 4 từ. Để thao tác tách từ tốt hơn, hãy đặt IFStheo nhu cầu của bạn : IFS=':'; find $PATH -perm +rwx ….
thao tác
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.