OS X 中的 Bash 脚本绝对路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3572030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash script absolute path with OS X
提问by The Mighty Rubber Duck
I am trying to obtain the absolute path to the currently running script on OS X.
我正在尝试获取 OS X 上当前正在运行的脚本的绝对路径。
I saw many replies going for readlink -f $0
. However since OS X's readlink
is the same as BSD's, it just doesn't work (it works with GNU's version).
我看到了很多回复readlink -f $0
。但是,由于 OS Xreadlink
与 BSD 相同,因此它不起作用(它适用于 GNU 版本)。
Is there an out-of-the-box solution to this?
是否有现成的解决方案?
采纳答案by John Kugelman
There's a realpath()
C function that'll do the job, but I'm not seeing anything available on the command-line. Here's a quick and dirty replacement:
有一个realpath()
C 函数可以完成这项工作,但我在命令行上看不到任何可用的东西。这是一个快速而肮脏的替代品:
#!/bin/bash
realpath() {
[[ = /* ]] && echo "" || echo "$PWD/${1#./}"
}
realpath "#!/bin/sh
realpath() {
OURPWD=$PWD
cd "$(dirname "")"
LINK=$(readlink "$(basename "")")
while [ "$LINK" ]; do
cd "$(dirname "$LINK")"
LINK=$(readlink "$(basename "")")
done
REALPATH="$PWD/$(basename "")"
cd "$OURPWD"
echo "$REALPATH"
}
realpath "$@"
"
This prints the path verbatim if it begins with a /
. If not it must be a relative path, so it prepends $PWD
to the front. The #./
part strips off ./
from the front of $1
.
如果路径以 a 开头,则会逐字打印路径/
。如果不是,它必须是一个相对路径,所以它$PWD
放在前面。的#./
部分剥去./
从的前面$1
。
回答by Oleg Mikheev
回答by Geoff Nixon
Ugh. I found the prior answers a bit wanting for a few reasons: in particular, they don't resolve multiple levels of symbolic links, and they are extremely "Bash-y". While the original question does explicitly ask for a "Bash script", it also makes mention of Mac OS X's BSD-like, non-GNU readlink
. So here's an attempt at some reasonable portability (I've checked it with bash as 'sh' and dash), resolving an arbitrary number of symbolic links; and it should also work with whitespace in the path(s), although I'm not sure of the behavior if there is white space the base name of the utility itself, so maybe, um, avoid that?
啊。由于以下几个原因,我发现先前的答案有点欠缺:特别是,它们不能解析多个级别的符号链接,而且它们非常“Bash-y”。虽然最初的问题确实明确要求“Bash 脚本”,但它也提到了 Mac OS X 的类似 BSD 的非 GNU readlink
。所以这里尝试了一些合理的可移植性(我已经用 bash 作为“sh”和破折号进行了检查),解析任意数量的符号链接;并且它也应该与路径中的空格一起使用,尽管我不确定实用程序本身的基本名称是否有空格,所以也许,嗯,避免这种情况?
python -c "import os; print(os.path.realpath(''))"
Hope that can be of some use to someone.
希望这对某人有用。
回答by nanav yorbiz
A more command-line-friendly variant of the Python solution:
Python 解决方案的更命令行友好的变体:
script_abspath=$(perl -e 'use Cwd "abs_path"; print abs_path(@ARGV[0])' -- "here=$(perl -e 'use File::Basename; use Cwd "abs_path"; print dirname(abs_path(@ARGV[0]));' -- "#!/usr/bin/env python
import os
import sys
print(os.path.realpath(sys.argv[1]))
")
")
回答by 4ae1e1
I was looking for a solution for use in a system provision script, i.e., run before Homebrew is even installed. Lacking a proper solution I'd just offload the task to a cross-platform language, e.g., Perl:
我正在寻找一种用于系统配置脚本的解决方案,即在 Homebrew 安装之前运行。缺乏适当的解决方案,我只是将任务卸载到跨平台语言,例如 Perl:
// realpath.c
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
{
if (argc > 1) {
for (int argIter = 1; argIter < argc; ++argIter) {
char *resolved_path_buffer = NULL;
char *result = realpath(argv[argIter], resolved_path_buffer);
puts(result);
if (result != NULL) {
free(result);
}
}
}
return 0;
}
More often what we actually want is the containing directory:
更多时候我们真正想要的是包含目录:
#Makefile
OBJ = realpath.o
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
realpath: $(OBJ)
gcc -o $@ $^ $(CFLAGS)
回答by acrazing
Use Python to get it:
使用 Python 获取:
#!/usr/bin/env bash
set -e
if ! which realpath >&/dev/null; then
if ! which brew >&/dev/null; then
msg="ERROR: This script requires brew. See https://brew.sh for installation instructions."
echo "$(tput setaf 1)$msg$(tput sgr0)" >&2
exit 1
fi
echo "Installing coreutils/realpath"
brew install coreutils >&/dev/null
fi
thisDir=$( dirname "`realpath "abs_path () {
echo "$(cd $(dirname "");pwd)/$(basename "")"
}
"`" )
echo "This script is run from \"$thisDir\""
回答by WaffleSouffle
Since there is a realpathas others have pointed out:
由于其他人指出存在真实路径:
realpath() {
path=`eval echo ""`
folder=$(dirname "$path")
echo $(cd "$folder"; pwd)/$(basename "$path");
}
Makefile:
生成文件:
realpath "../scripts/test.sh"
Then compile with make
and put in a soft link with:ln -s $(pwd)/realpath /usr/local/bin/realpath
然后编译make
并放入一个软链接:ln -s $(pwd)/realpath /usr/local/bin/realpath
回答by Clay Bridges
On macOS, the only solution that I've found to this that reliably handles symlinks is by using realpath
. Since this requires brew install coreutils
, I just automated that step. My implementation looks like this:
在 macOS 上,我找到的唯一可靠处理符号链接的解决方案是使用realpath
. 由于这需要brew install coreutils
,我只是自动化了这一步。我的实现是这样的:
realpath "~/Test/../Test/scripts/test.sh"
This errors if they don't have brew
installed, but you could alternatively just install that too. I just didn't feel comfortable automating something that curls arbitrary ruby code from the net.
如果尚未brew
安装,则会出现此错误,但您也可以安装它。我只是觉得自动化一些从网络上卷曲任意 ruby 代码的东西并不舒服。
Note that this an automated variation on Oleg Mikheev's answer.
请注意,这是 Oleg Mikheev答案的自动变体。
One important test
一项重要的测试
One good test of any of these solutions is:
对任何这些解决方案的一个很好的测试是:
- put the code in a script file somewhere
- in another directory, symlink (
ln -s
) to that file - run the script from that symlink
- 将代码放在某个脚本文件中
- 在另一个目录中,符号链接 (
ln -s
) 到该文件 - 从该符号链接运行脚本
Does the solution dereference the symlink, and give you the original directory? If so, it works.
解决方案是否取消引用符号链接,并为您提供原始目录?如果是这样,它的工作原理。
回答by Logu
dirname
will give the directory name of /path/to/file
, i.e. /path/to
.
dirname
将给出 的目录名称/path/to/file
,即/path/to
。
cd /path/to; pwd
ensures that the path is absolute.
cd /path/to; pwd
确保路径是绝对的。
basename
will give just the filename in /path/to/file
, i.e.file
.
basename
将只给出文件名/path/to/file
,即file
.
回答by Evgeny Karpov
realpath for Mac OS X
Mac OS X 的真实路径
##代码##Example with related path:
具有相关路径的示例:
##代码##Example with home folder
主文件夹示例
##代码##