如何在Mac OS X上的Shell脚本中检索绝对文件名?


19

我想检索当前正在执行的脚本文件的绝对文件名。链接也应该解决。

在Linux上,这似乎是这样完成的:

$(readlink -mn "$0")

readlink似乎工作非常不同的Mac OS X上

我已经读到这是使用

$(realpath $0)

在BSD中,但这也不起作用。Mac OS X没有realpath

任何想法?


1
看到这个问题在上SO:stackoverflow.com/questions/799679/...
泰勒马格斯


Answers:


19

我为此作弊并使用perl:

#!/bin/bash
dirname=`perl -e 'use Cwd "abs_path";print abs_path(shift)' $0`
echo $dirname

您可能会以为我会用perl编写整个脚本,而且经常这样做,但并非总是如此。


这很有效,非常感谢。我会尽快给你投票。有没有人可以做到这一点?
湖西

1
恐怕这是最好的。(鉴于人们可以在Google上找到许多多行“纯壳”黑客。)
Arjan

另一个可能性(虽然很丑)是遍历“ ..”路径,记忆(通过递归或数组),直到“ ..”返回您刚刚拥有的相同文件(即:您位于顶部),然后重新组装走的路。我已经看到Legato的Networker备份软件在strace期间执行此操作,以此作为获取“真实”路径的一种方法(但可能不是绝对的)。但这将比上面更多。
ericslaw

不知道为什么有人将代码修改为使用$ 1而不是$ 0。bash脚本的第一个参数不是$ 1吗?我想要执行bash脚本的路径,而不是第一个参数。
ericslaw

27
#!/usr/bin/env bash
scriptDir="$(cd "$(dirname "$0")" && pwd -P)"

也可以在MacOSX中使用。
Alexar'1

1
太好了!还有许多其他过于复杂的答案。
杰森·S

3
这仅适用于符号链接目录中的文件,而不适用于通常的符号链接文件
Gerhard Burger

1
unset -v CDPATH设置cd之前,这也很有帮助,因为如果设置了CDPATH,cd可能会导致不必要的输出。
Binary Phile '17

要至少处理文件符号链接的单层,您还可以使用兼容的方式与readlink(macs没有-f)进行测试: scriptDir=$(unset -v CDPATH; cd "$(dirname "$(readlink "$BASH_SOURCE" || echo "$BASH_SOURCE)")" && pwd -P)
Binary Phile

0

这可以处理符号链接的组合,并且适用于文件和文件夹:

#!/usr/bin/env bash
realpath()
{
    if ! pushd $1 &> /dev/null; then 
        pushd ${1##*/} &> /dev/null
        echo $( pwd -P )/${1%/*}
    else
        pwd -P
    fi
    popd > /dev/null
}

但是它不支持realpath的--relative-to。这将需要此处描述的转换 。


0

另一种方法:

# Install.
brew install coreutils

# Use the GNU variant.
grealpath --help
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.