我正在尝试获取在OS X上当前运行脚本的绝对路径。
我看到很多回复都使用readlink -f $0
。然而,由于OS X的readlink
与BSD的相同,所以它不起作用(它在GNU版本中有效)。
是否有开箱即用的解决方案?
这三个简单的步骤将解决此问题以及其他许多OS X问题:
brew install coreutils
grealpath .
(3) 可能会更改为 realpath
,请参见 (2) 的输出
$( cd "$(dirname "$0")" ; pwd -P )
对我来说就很好用。 - Jason SXXX
的目录,有人输入cd xxx
,那么pwd
将返回.../xxx
。除了这个答案外,上面的所有解决方案都会返回xxx
,而您真正想要的是XXX
。谢谢! - Andrewrealpath
,那么当你几乎肯定需要 coreutils
中的其他项目时会发生什么?也要在 bash 中重写这些函数吗?:P - Ezekiel Victor有一个C函数realpath()
可以完成这个任务,但我没有看到任何可用于命令行的东西。这里是一个快速而肮脏的替代方法:
#!/bin/bash
realpath() {
[[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}
realpath "$0"
如果路径以 /
开头,则原样打印该路径。否则,它必须是相对路径,因此将 $PWD
添加到前面。 #./
部分从 $1
的前面删除了 ./
。
realpath ../something
返回 $PWD/../something
。其中,realpath
是一个命令,用于获取输入路径的绝对路径;而 $PWD
则是当前工作目录的环境变量。 - Lrirealpath
命令存在,则不执行任何操作。如果不存在,则定义一个名为 realpath()
的函数并执行其中的代码。 - Kara Brightwell$0
是脚本本身,$1
是脚本的第一个参数,不是我们想要的。 - John Kugelman出于几个原因,我觉得答案有点欠缺:
特别是,它们不能解决多级符号链接,并且它们非常“Bash-y”。
虽然原始问题明确要求一个“Bash脚本”,但它也提到了Mac OS X的类似BSD的非GNU readlink
。
所以这里尝试了一些合理的可移植性方法(我已经使用bash作为'sh'和dash进行了检查),可以解决任意数量的符号链接;它还应该适用于路径中的空格。
此答案先前已进行编辑,重新添加了local
bashism。此答案的重点是一个可移植的POSIX解决方案。我已将其编辑为通过更改为子shell函数而不是内联函数来解决变量作用域。请勿编辑。
#!/bin/sh
realpath() (
OURPWD=$PWD
cd "$(dirname "$1")"
LINK=$(readlink "$(basename "$1")")
while [ "$LINK" ]; do
cd "$(dirname "$LINK")"
LINK=$(readlink "$(basename "$1")")
done
REALPATH="$PWD/$(basename "$1")"
cd "$OURPWD"
echo "$REALPATH"
)
realpath "$@"
希望这对某人有所帮助。
BASENAME=$(basename "$LINK")
,并在第二个LINK设置器和REALPATH设置器中使用它。 - stroborobo..
父级引用的方式并不像 realpath
那样。如果安装了 homebrew 的 coreutils
,可以尝试运行 ln -s /var/log /tmp/linkexample
,然后运行 realpath /tmp/linkexample/../
;这将打印出 /private/var
。但你的函数则生成了 /tmp/linkexample/..
,因为 ..
不是一个符号链接。 - Martijn PietersPython解决方案的更加适合命令行的变体:
python -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ./my/path
python -c "import os; import sys; print(os.path.realpath(sys.argv[1]))"
。 - Alex Chamberlain/usr/bin
目录下?您可能会惊讶于自己已经在使用多少。 - Philip Couling我检查了每一个回答,但错过了Jason S于2016年7月14日3:12提供的最佳答案(在我看来),并留下了评论区。
所以在这里,如果有像我一样倾向于检查已回答问题而没有时间阅读每一个评论的人:
$( cd "$(dirname "$0")" ; pwd -P )
帮助:
NAME
pwd -- return working directory name
SYNOPSIS
pwd [-L | -P]
DESCRIPTION
The pwd utility writes the absolute pathname of the current working
directory to the standard output.
Some shells may provide a builtin pwd command which is similar or identi-
cal to this utility. Consult the builtin(1) manual page.
The options are as follows:
-L Display the logical current working directory.
-P Display the physical current working directory (all symbolic
links resolved).
正如其他人所指出的那样,由于存在realpath:
// 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;
}
Makefile:
#Makefile
OBJ = realpath.o
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
realpath: $(OBJ)
gcc -o $@ $^ $(CFLAGS)
然后使用make
进行编译,并使用以下命令创建软链接:
ln -s $(pwd)/realpath /usr/local/bin/realpath
gcc realpath.c -o /usr/local/bin/realpath
吗? - Alexander Mills/usr/local/bin
的权限。 - tripleeeabs_path () {
echo "$(cd $(dirname "$1");pwd)/$(basename "$1")"
}
dirname
会返回目录路径,例如/path/to/file
的结果是/path/to
。
cd /path/to; pwd
确保路径是绝对路径。
basename
会返回文件名,例如在/path/to/file
中,结果是file
。
我正在寻找一个用于系统设置脚本的解决方案,即在Homebrew甚至未安装之前运行。由于没有合适的解决方案,我只能将任务转交给跨平台语言,例如Perl:
script_abspath=$(perl -e 'use Cwd "abs_path"; print abs_path(@ARGV[0])' -- "$0")
here=$(perl -e 'use File::Basename; use Cwd "abs_path"; print dirname(abs_path(@ARGV[0]));' -- "$0")
FULLPATH=$(perl -e"use Cwd 'abs_path'; print abs_path('$0')")
。有什么反对的理由吗? - F Pereira''
并非万无一失。例如,如果$0
包含单引号,则会出现错误。一个非常简单的例子:在/tmp/'/test.sh
中尝试您的版本,并通过其完整路径调用/tmp/'/test.sh
。 - 4ae1e1/tmp/'.sh
。 - 4ae1e1使用Python获取它:
#!/usr/bin/env python
import os
import sys
print(os.path.realpath(sys.argv[1]))
Mac OS X 的 realpath
realpath() {
path=`eval echo "$1"`
folder=$(dirname "$path")
echo $(cd "$folder"; pwd)/$(basename "$path");
}
相关路径的示例:
realpath "../scripts/test.sh"
以家目录为例
realpath "~/Test/../Test/scripts/test.sh"
..
调用它时,它不能产生正确的答案,因此我添加了一个检查,如果给定的路径是目录:if test -d $path ; then echo $(cd "$path"; pwd) ; else [...]
- Herbert Poul"$(dirname $(dirname $(realpath $0)))"
可以工作,所以需要其他的东西... - Alexander Mills..
父引用,而不是之后;尝试使用homebrew coreutils
安装创建链接ln -s /var/log /tmp/linkexample
,然后运行realpath /tmp/linkexample/../
;这将打印/private/var
。但是您的函数却产生了/tmp/linkexample/..
,因为cd
后pwd
仍然显示/tmp/linkexample
。 - Martijn Pieters
$( cd "$(dirname "$0")" ; pwd -P )
- Jason Sbrew install coreutils
。 - Vojtěch