如何返回给定可执行文件的目录?

如何返回给定可执行文件的目录?

如果我想返回给定可执行文件的路径,我可以运行:

which mysql

例如返回:

/usr/bin/mysql

我只想返回:

/usr/bin

我怎样才能做到这一点?

答案1

executable=mysql

executable_path=$(command -v -- "$executable") &&
  dirname -- "$executable_path"

不要使用which)。

$executable当然,如果是 shell 内置函数、函数或别名,那么这将不起作用。我不知道有任何 shellmysql是内置的。除非您之前定义了它们,否则它不会是函数或别名,但您应该了解它。一个例外可能是bash支持导出函数。

$ bash -c 'command -v mysql'
/usr/bin/mysql
$ mysql='() { echo test;}' bash -c 'command -v mysql'
mysql

答案2

哪个

一般来说,应该避免使用该命令。

为什么?

因为它在构建时使用您当前的环境,$PATH在查找可执行文件时将对其进行评估。这可能会在处理 shell 脚本等时导致混乱,这些脚本在执行时可能会使用您的和文件$PATH构建的内容。~/.bashrc~/.bash_profile

例如:

# path to start
$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/sam/bin

# let's change it
$ export PATH=/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin

$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin

# simulate a new env. for a shell script
$ bash -lc "echo \$PATH"
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/sam/bin

请注意,如果执行的 shell 脚本将具有原始环境,而不是当前环境!

类型

您还可以使用以下命令type在您的环境中查找可执行文件:

$ type ls
ls is aliased to `ls --color=auto'

或者要查看所有内容,请使用-a开关:

$ type -a ls
ls is aliased to `ls --color=auto'
ls is /bin/ls

type将向您显示别名和位置。不过,为了找到目录,command最好使用 @StephaneChazelas 解决方案。

哪里

您也可以使用该命令whereis,但这不会使用您的环境,它有一组硬编码的目录可供查找。请参阅男人在哪里更多细节。

定位

这可能会让人们感到困惑,但有些发行版包含一个从 cron 作业运行的工具,通常每天运行一次,它会扫描整个磁盘并构建一个小数据库文件,然后您可以使用该locate命令进行搜索。

  • /etc/cron.daily/mlocate.cron我的 Fedora 14 系统上调用了 cron 作业。
  • 执行扫描的工具称为/usr/bin/updatedb
  • DB 文件位于此处:/var/lib/mlocate/mlocate.db.

使用我认为有点黑客的方法,您可以诱使locate只查找名为ls如下的文件:

$ locate -b '\ls'
/bin/ls
/usr/share/javadoc/java-1.6.0-openjdk/api/org/w3c/dom/ls
/usr/share/javadoc/java-1.6.0-openjdk/jre/api/plugin/dom/org/w3c/dom/ls
/usr/share/locale/l10n/ls
/var/cache/abrt-di/usr/src/debug/gcc-4.5.1-20100924/libjava/classpath/external/w3c_dom/org/w3c/dom/ls
/var/cache/abrt-di/usr/src/debug/gcc-4.5.1-20100924/libjava/classpath/gnu/xml/dom/ls

上述方法有效,因为您是\一个通配符,因此这会禁用 的隐式ls替换*ls*

请参阅找到手册页更多细节。

什么是

一个鲜为人知的工具称为whatis.这个与 类似locate,因此它由数据库支持。然而,它对于查找命令很有用:

$ whatis ls
ls                   (1)  - list directory contents
ls                   (1p)  - list directory contents

该工具是从 cron 作业调用的/etc/cron.daily/makewhatis.cron。但是,从系统上的页面makewhatis构建其数据库。man

您可以在中查看更多相关信息makewhatis 手册页

只是目录名吗?

dirpath您可以针对我上面提到的命令生成的任何输出使用该命令来仅获取目录组件。

dirpath不进行检查,因此您可以为它提供任何类型的文件路径,它会给您目录部分:

$ dirname /some/path/to/a/script
/some/path/to/a

答案3

使用 xargs 相当简单:

which mysql | xargs dirname

答案4

作为其他的解释了,不要使用which

您可以编写一个小的 shell 函数来迭代该PATH变量。

which-directory () (
  IFS=:
  set -g
  for d in $PATH; do
    if [ -z "$d" ]; then d=.; fi
    if [ -x "$d/$1" ]; then printf '%s\n' "$d"; return; fi
  done
  return 1
)

或者,您可以致电command -v.这会报告别名和函数以及外部命令。如果您有一个别名或函数mysql调用带有附加参数的同名外部命令,则可以command -v在新启动的未定义任何函数或别名的 shell 中进行调用。请注意,仅当别名或函数调用同名的外部命令时,这才正确。以下两个单行代码是等效的(假设您的 PATH 上没有包含换行符的目录或可执行文件名)。

dirname -- "$(sh -c 'command -v "$0"' -- mysql)"
sh -c 'command -v "$0"' -- mysql | sed -e 's!.*/!!'

在 zsh 中,这一行代码做了同样的事情:

echo =mysql(:h)

相关内容