列出当前PATH中的所有文件/二进制文件


10

有没有一种“简便”的方式来运行“ ls -la”样式的命令,以列出当前PATH中的所有文件/可执行二进制文件?

(我打算将输出通过管道传递到grep,以查找前缀未知但基本已知的“名称”的命令,这种情况下,bash中的自动补全/制表符实际上是无用的。因此,某种形式的“反向自动完整功能” ...)


你能举个例子吗?有什么不同ls -la
John Siu

“ ls -la” /“ ls -a”仅列出当前目录(pwd)中的文件。我想列出PATH中包含的所有目录中的所有(可执行)文件。
sme 2013年

Answers:


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. 

很好,这是我一直在寻找的东西。它甚至在当前目录中包含可执行二进制文件。谢谢。
sme 2013年

效果很好...在bash中。
伊曼纽尔·伯格

有没有办法列出每一个的路径which $(compgen -A function -abck)
h3rrmiller 2013年

我找不到更好的选择。
Nykakin

3

这是一个列出目录内容的函数$PATH。如果传递了参数,则该函数仅列出名称包含参数之一的命令。参数被解释为全局模式。

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
}

像许多事情一样,这在zsh中更容易。

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

参数扩展中^字符会导致将与数组连接的文本添加到每个数组元素,例如prints 。看起来像是漫画中的侮辱,但实际上是普通字符,通配符,带修饰符的特殊参数(位置参数的数组),以及。是glob限定符,如果没有匹配项,则得到一个空扩展名,其后是history修饰符,以仅保留每个匹配项的基本名称(“ tail”)。path=(/bin /usr/bin); echo $^path/foo/bin/foo /usr/bin/foo
/*$^@*/*$@^*
(N:t) N t

更神秘,避免了外部调用,但这只是表面上的兴趣:

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

实际上,您可能正在寻找该apropos命令,该命令搜索简短说明中包含关键字的命令手册页。一个限制是,它只能查找具有手册页的命令。


在zsh函数中,第二个函数^似乎导致“ no arguments”调用没有输出?如果将其删除,则可以将它们全部列出,并且仍然搜索单个关键字(而不是它们的列表)。在(Non:t)似乎是说,星号应该扩大?无法找出最后一个。
伊曼纽尔·伯格

@EmanuelBerg对,谢谢。我添加了线路噪音的说明。
吉尔斯(Gillles)“所以-别再邪恶了”

好的,让我们看一下:如果没有参数,则将“它们”设置为空,因为那里有什么(当没有)时,仍然以某种方式破坏了您下一步的工作?另外,我从未见过小写字母path,但是当我在shell中运行它时,它的确是$ PATH,但带有空格而不是:。其余的一切都很清晰:)
伊曼纽尔·伯格

@EmanuelBerg否:如果没有参数,则将参数数组设置为包含空字符串的单元素数组。这样,没有参数意味着每个包含空字符串的名称都匹配,即每个名称都匹配。$path是zsh的功能:它是一个绑定参数,一个数组,在更新时PATH会自动更新,反之亦然。
吉尔斯(Gillles)“所以-别再邪恶了”

啊哈,现在我明白了!哇,那是非正统的!
伊曼纽尔·伯格

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" ; 
}

搜索结果仅匹配:至少设置了一个“ x”(可执行)位,而不是目录。

并将其与正则表达式列表一起使用:

findinpath awk sed '\.sh$'

正则表达式“。” 将向您显示一切
Olivier Dulac 2013年

使用常规IFS,您可以在$ PATH中找到以下重复项:echo $PATH | tr ':' '\n' | sort | uniq -d
Olivier Dulac 2013年

1
我尝试了所有答案的代码,这是唯一真正给我所需内容的代码(PATH中给定命令的每个实例的完整路径)。
克里斯·佩奇

我很高兴它有所帮助:)
Olivier Dulac 2015年

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

首先,我们回显$PATHsed并将“:”替换为“”。

然后我们在所有这些东西上进行查找,以使用rwx查找文件并回显它们。

2> /dev/null所以find不会打印错误


3
你需要-maxdepth 1-type f你的发现,否则你会发现子目录和它们的文件(路径搜索不会)。另外,您的权限测试很奇怪- +x我认为应该只是为了?
derobert 2013年

如果有效的空白条目与“。”相同(例如:/bin或),则无法处理边缘情况/bin::/usr/bin。尝试添加s/::/:.:/;s/^:/.:/;s/:$/:./sed命令。
Arcege

实际上,它find可以搜索更多路径,因此您可以在不使用循环的情况下执行此操作:find $(echo $PATH | sed -e 's/\:/\ /g') -perm +rwx …当然,包含空格的目录名称会将其弄乱,但是基于循环的目录名称仍然存在相同的问题。
manatwork 2013年

@manatwork你是对的。我刚刚添加了引号来解决该问题
h3rrmiller 2013年

对不起,那解决不了什么。问题在于用空格替换冒号以允许单词拆分。因此,您将“ / foo bar:/ fiz baz”转换为“ / foo bar / fiz baz”,然后将其传递给for。因此for将遍历4个单词的列表。要更好地操作分词,请IFS根据需要设置IFS=':'; find $PATH -perm +rwx …
manatwork 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.