给定相对路径时,是否有命令检索绝对路径?
例如,我希望$ line在dir中包含每个文件的绝对路径。 ./etc/
find ./ -type f | while read line; do
echo $line
done
给定相对路径时,是否有命令检索绝对路径?
例如,我希望$ line在dir中包含每个文件的绝对路径。 ./etc/
find ./ -type f | while read line; do
echo $line
done
Answers:
用:
find "$(pwd)"/ -type f
获取所有文件或
echo "$(pwd)/$line"
显示完整路径(如果相对路径很重要)
$(pwd)
代替$PWD
?(是的,我知道pwd
是内置的)
尝试realpath
。
~ $ sudo apt-get install realpath # may already be installed
~ $ realpath .bashrc
/home/username/.bashrc
为避免扩展符号链接,请使用realpath -s
。
答案来自“ bash / fish命令以打印文件的绝对路径 ”。
realpath
在Mac上似乎不可用(OS X 10.11“ El Capitan”)。:-(
realpath
似乎在CentOS 6上也不可用
brew install coreutils
将带来realpath
realpath
上已经存在。我不必单独安装它。
realpath
它在Windows的Git上可用(至少对我而言)。
如果您安装了coreutils软件包,通常可以使用readlink -f relative_file_name
它来检索绝对的软件包(解决所有符号链接)
brew install coreutils
。但是,该可执行文件由ag开头:greadlink -f relative_file_name
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
UPD一些解释
"$1"
dirname "$1"
cd "$(dirname "$1")
进入这个相对目录并通过运行pwd
shell命令获取它的绝对路径$(basename "$1")
echo
就realpath
或readlink -f
做什么。例如,它在最后一个组件是符号链接的路径上不起作用。
-P
选项pwd
:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
对于它的价值,我投票选择了答案,但想分享一个解决方案。缺点是,它仅适用于Linux-我花了大约5分钟的时间试图找到与OSX相当的产品,然后才出现Stack Overflow。我敢肯定它在那里。
在Linux上,您可以readlink -e
与一起使用dirname
。
$(dirname $(readlink -e ../../../../etc/passwd))
产量
/etc/
然后使用dirname
的姐姐basename
来获取文件名
$(basename ../../../../../passwd)
产量
passwd
全部放在一起。
F=../../../../../etc/passwd
echo "$(dirname $(readlink -e $F))/$(basename $F)"
产量
/etc/passwd
如果您以目录为目标,basename
则很安全,将不返回任何内容,并且在最终输出中只会出现双斜杠。
dirname
,readlink
和basename
。这帮助我获得了符号链接的绝对路径,而不是它的目标。
/home/GKFX
并输入touch newfile
,那么在按Enter之前,您可以算出我的意思是“创建/ home / GKFX / newfile”,这是一个尚不存在的文件的绝对路径。
我认为这是最便携的:
abspath() {
cd "$(dirname "$1")"
printf "%s/%s\n" "$(pwd)" "$(basename "$1")"
cd "$OLDPWD"
}
如果路径不存在,它将失败。
dirname
是GNU核心实用程序,我相信并非所有unixen都通用。
dirname
是POSIX标准实用程序,请参见此处:pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html
${1##*/}
一天使用的版本,现在我用basename "$1"
它替换了该垃圾桶似乎终于可以正确处理了以/结尾的路径。
../..
realpath
可能是最好的
但是...
最初的问题从一开始就很困惑,其中一个例子与所述问题关系不大。
所选答案实际上回答了给定的示例,而不是标题中的问题。第一个命令就是那个答案(真的吗?我怀疑),并且不用'/'也可以做到。我看不到第二个命令在做什么。
几个问题是混杂的:
将相对路径名更改为绝对路径名,无论它代表什么,可能什么也没有。(通常,如果发出诸如之类的命令touch foo/bar
,则foo/bar
在实际创建文件之前,路径名必须为您存在,并且可能在计算中使用。)
可能有多个绝对路径名表示相同的文件(或潜在文件),这主要是由于路径上的符号链接(符号链接),但可能是由于其他原因(设备可能以只读方式安装两次)。一个人可能想要也可能不想明确地解析此类符号链接。
到达非符号链接文件或名称的符号链接链的末尾。这可能会或可能不会产生绝对路径名,这取决于完成方式。并且可能会或可能不想将其解析为绝对路径名。
readlink foo
不带选项的命令只有在其参数为实的情况下才能给出答案foo
是符号链接且该答案是该符号链接的值。没有其他链接。答案可能是相对的:symlink参数的值是多少。
然而, readlink
具有选项(-f -e或-m)适用于所有文件,并为该参数实际表示的文件提供一个绝对路径名(没有符号链接的绝对路径名)。
这对于不是符号链接的任何内容都可以正常工作,尽管可能希望使用绝对路径名而不解析路径上的中间符号链接。这是通过命令完成的realpath -s foo
对于symlink自变量,readlink
其选项将再次解析到该自变量绝对路径上的所有符号链接,但这也将包括跟随该参数值可能遇到的所有符号链接。如果您需要一个指向符号symlink本身而不是其链接对象的绝对路径,则可能不希望这样做。同样,如果foo
是符号链接,realpath -s foo
将获得绝对路径而不解决符号链接,包括作为参数给出的符号链接。
如果不-s
选择该选项,realpath
则与几乎一样
readlink
,除了简单地读取链接的值以及其他几件事。对我来说,readlink
目前尚不清楚为什么会有它的选择,显然会给带来不希望的冗余
realpath
。
探究网络并没有多说什么,只是整个系统之间可能会有一些变化。
结论:realpath
至少在这里要求的使用情况下,它是最好的命令,具有最大的灵活性。
我最喜欢的解决办法是在一个由@EugenKonkov,因为它并不意味着其他公用事业存在(的coreutils软件包)。
但是,相对路径“”失败了。和“ ..”,因此这里是处理这些特殊情况的略有改进的版本。
但是,如果用户没有权限cd
进入相对路径的父目录,它仍然会失败。
#! /bin/sh
# Takes a path argument and returns it as an absolute path.
# No-op if the path is already absolute.
function to-abs-path {
local target="$1"
if [ "$target" == "." ]; then
echo "$(pwd)"
elif [ "$target" == ".." ]; then
echo "$(dirname "$(pwd)")"
else
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
fi
}
欧根(Eugen)的回答对我而言并不奏效,但这确实可以做到:
absolute="$(cd $(dirname \"$file\"); pwd)/$(basename \"$file\")"
旁注,您当前的工作目录不受影响。
最好的解决方案,恕我直言,是发布在这里的解决方案:https : //stackoverflow.com/a/3373298/9724628。
它确实需要python才能工作,但是它似乎涵盖了所有或大多数边缘情况,并且是非常可移植的解决方案。
python -c "import os,sys; print(os.path.realpath(sys.argv[1]))" path/to/file
python -c "import os,sys; print(os.path.abspath(sys.argv[1]))" path/to/file
如果您使用的是Mac OS X上的bash既不具有真实路径存在也没有了它的readlink可以打印的绝对路径,你可以有选择,只能自己编码的版本进行打印。这是我的实现:
(纯扑)
abspath(){
local thePath
if [[ ! "$1" =~ ^/ ]];then
thePath="$PWD/$1"
else
thePath="$1"
fi
echo "$thePath"|(
IFS=/
read -a parr
declare -a outp
for i in "${parr[@]}";do
case "$i" in
''|.) continue ;;
..)
len=${#outp[@]}
if ((len==0));then
continue
else
unset outp[$((len-1))]
fi
;;
*)
len=${#outp[@]}
outp[$len]="$i"
;;
esac
done
echo /"${outp[*]}"
)
}
(使用gawk)
abspath_gawk() {
if [[ -n "$1" ]];then
echo $1|gawk '{
if(substr($0,1,1) != "/"){
path = ENVIRON["PWD"]"/"$0
} else path = $0
split(path, a, "/")
n = asorti(a, b,"@ind_num_asc")
for(i in a){
if(a[i]=="" || a[i]=="."){
delete a[i]
}
}
n = asorti(a, b, "@ind_num_asc")
m = 0
while(m!=n){
m = n
for(i=1;i<=n;i++){
if(a[b[i]]==".."){
if(b[i-1] in a){
delete a[b[i-1]]
delete a[b[i]]
n = asorti(a, b, "@ind_num_asc")
break
} else exit 1
}
}
}
n = asorti(a, b, "@ind_num_asc")
if(n==0){
printf "/"
} else {
for(i=1;i<=n;i++){
printf "/"a[b[i]]
}
}
}'
fi
}
(纯bsd awk)
#!/usr/bin/env awk -f
function abspath(path, i,j,n,a,b,back,out){
if(substr(path,1,1) != "/"){
path = ENVIRON["PWD"]"/"path
}
split(path, a, "/")
n = length(a)
for(i=1;i<=n;i++){
if(a[i]==""||a[i]=="."){
continue
}
a[++j]=a[i]
}
for(i=j+1;i<=n;i++){
delete a[i]
}
j=0
for(i=length(a);i>=1;i--){
if(back==0){
if(a[i]==".."){
back++
continue
} else {
b[++j]=a[i]
}
} else {
if(a[i]==".."){
back++
continue
} else {
back--
continue
}
}
}
if(length(b)==0){
return "/"
} else {
for(i=length(b);i>=1;i--){
out=out"/"b[i]
}
return out
}
}
BEGIN{
if(ARGC>1){
for(k=1;k<ARGC;k++){
print abspath(ARGV[k])
}
exit
}
}
{
print abspath($0)
}
例:
$ abspath I/am/.//..//the/./god/../of///.././war
/Users/leon/I/the/war
如果相对路径是目录路径,请尝试我的,最好是:
absPath=$(pushd ../SOME_RELATIVE_PATH_TO_Directory > /dev/null && pwd && popd > /dev/null)
echo $absPath
echo "mydir/doc/ mydir/usoe ./mydir/usm" | awk '{ split($0,array," "); for(i in array){ system("cd "array[i]" && echo $PWD") } }'
对@ ernest-a相当不错的版本的改进:
absolute_path() {
cd "$(dirname "$1")"
case $(basename $1) in
..) echo "$(dirname $(pwd))";;
.) echo "$(pwd)";;
*) echo "$(pwd)/$(basename $1)";;
esac
}
这正确处理了路径的最后一个元素为的情况..
,在这种情况下"$(pwd)/$(basename "$1")"
,@ ernest-a的答案将作为as出现accurate_sub_path/spurious_subdirectory/..
。
这是所有其他解决方案的链式解决方案,例如,realpath
由于未安装或因错误代码而退出时失败,然后尝试下一个解决方案,直到找到正确的路径。
#!/bin/bash
function getabsolutepath() {
local target;
local changedir;
local basedir;
local firstattempt;
target="${1}";
if [ "$target" == "." ];
then
printf "%s" "$(pwd)";
elif [ "$target" == ".." ];
then
printf "%s" "$(dirname "$(pwd)")";
else
changedir="$(dirname "${target}")" && basedir="$(basename "${target}")" && firstattempt="$(cd "${changedir}" && pwd)" && printf "%s/%s" "${firstattempt}" "${basedir}" && return 0;
firstattempt="$(readlink -f "${target}")" && printf "%s" "${firstattempt}" && return 0;
firstattempt="$(realpath "${target}")" && printf "%s" "${firstattempt}" && return 0;
# If everything fails... TRHOW PYTHON ON IT!!!
local fullpath;
local pythoninterpreter;
local pythonexecutables;
local pythonlocations;
pythoninterpreter="python";
declare -a pythonlocations=("/usr/bin" "/bin");
declare -a pythonexecutables=("python" "python2" "python3");
for path in "${pythonlocations[@]}";
do
for executable in "${pythonexecutables[@]}";
do
fullpath="${path}/${executable}";
if [[ -f "${fullpath}" ]];
then
# printf "Found ${fullpath}\\n";
pythoninterpreter="${fullpath}";
break;
fi;
done;
if [[ "${pythoninterpreter}" != "python" ]];
then
# printf "Breaking... ${pythoninterpreter}\\n"
break;
fi;
done;
firstattempt="$(${pythoninterpreter} -c "import os, sys; print( os.path.abspath( sys.argv[1] ) );" "${target}")" && printf "%s" "${firstattempt}" && return 0;
# printf "Error: Could not determine the absolute path!\\n";
return 1;
fi
}
printf "\\nResults:\\n%s\\nExit: %s\\n" "$(getabsolutepath "./asdfasdf/ asdfasdf")" "${?}"
您可以使用bash字符串替换任何相对路径$ line:
line=$(echo ${line/#..\//`cd ..; pwd`\/})
line=$(echo ${line/#.\//`pwd`\/})
echo $line
基本的字符串开头替换遵循公式
$ {string /#substring / replacement}
,在此处进行了很好的讨论:https : //www.tldp.org/LDP/abs/html/string-manipulation.html
该\
字符否定/
的时候,我们希望它是我们查找/替换字符串的一部分。