Linux 在 bash 中扩展一个可能的相对路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7126580/
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
Expand a possible relative path in bash
提问by laar
As arguments to my script there are some file paths. Those can, of course, be relative (or contain ~). But for the functions I've written I need paths that are absolute, but do not have their symlinks resolved.
作为我的脚本的参数,有一些文件路径。当然,这些可以是相对的(或包含 ~)。但是对于我编写的函数,我需要绝对路径,但没有解析它们的符号链接。
Is there any function for this?
有什么功能吗?
回答by Amir Afghani
MY_PATH=$(readlink -f $YOUR_ARG)
will resolve relative paths like "./"
and "../"
MY_PATH=$(readlink -f $YOUR_ARG)
将解析像"./"
和这样的相对路径"../"
Consider this as well (source):
也请考虑这一点(来源):
#!/bin/bash
dir_resolve()
{
cd "" 2>/dev/null || return $? # cd to desired directory; if fail, quell any error messages but return exit status
echo "`pwd -P`" # output full, link-resolved path
}
# sample usage
if abs_path="`dir_resolve \"\"`"
then
echo " resolves to $abs_path"
echo pwd: `pwd` # function forks subshell, so working directory outside function is not affected
else
echo "Could not reach "
fi
回答by Mike Samuel
http://www.linuxquestions.org/questions/programming-9/bash-script-return-full-path-and-filename-680368/page3.htmlhas the following
function abspath {
if [[ -d "" ]]
then
pushd "" >/dev/null
pwd
popd >/dev/null
elif [[ -e ]]
then
pushd "$(dirname "")" >/dev/null
echo "$(pwd)/$(basename "")"
popd >/dev/null
else
echo "" does not exist! >&2
return 127
fi
}
which uses pushd
/popd
to get into a state where pwd
is useful.
它使用pushd
/popd
进入pwd
有用的状态。
回答by Vitaly Kushner
on OS X you can use
在 OS X 上你可以使用
stat -f "%N" YOUR_PATH
on linux you might have realpath
executable. if not, the following might work (not only for links):
在 linux 上,您可能有realpath
可执行文件。如果没有,以下可能有效(不仅适用于链接):
readlink -c YOUR_PATH
回答by David G
Do you have to use bash exclusively? I needed to do this and got fed up with differences between Linux and OS X. So I used PHP for a quick and dirty solution.
你必须只使用 bash 吗?我需要这样做,并且对 Linux 和 OS X 之间的差异感到厌烦。所以我使用 PHP 作为快速而肮脏的解决方案。
#!/usr/bin/php <-- or wherever
<?php
{
if($argc!=2)
exit();
$fname=$argv[1];
if(!file_exists($fname))
exit();
echo realpath($fname)."\n";
}
?>
I know it's not a very elegant solution but it does work.
我知道这不是一个非常优雅的解决方案,但它确实有效。
回答by andsens
Simple one-liner:
简单的单线:
function abs_path {
(cd "$(dirname '')" &>/dev/null && printf "%s/%s" "$PWD" "${1##*/}")
}
Usage:
用法:
function do_something {
local file=$(abs_path )
printf "Absolute path to %s: %s\n" "" "$file"
}
do_something $HOME/path/to/some\ where
I am still trying to figure out how I can get it to be completely oblivious to whether the path exists or not (so it can be used when creating files as well).
我仍在试图弄清楚如何让它完全忘记路径是否存在(因此它也可以在创建文件时使用)。
回答by sja
Maybe this is more readable and does not use a subshell and does not change the current dir:
也许这更具可读性并且不使用子shell并且不更改当前目录:
dir_resolve() {
local dir=`dirname ""`
local file=`basename ""`
pushd "$dir" &>/dev/null || return $? # On error, return error code
echo "`pwd -P`/$file" # output full, link-resolved path with filename
popd &> /dev/null
}
回答by keen
self edit, I just noticed the OP said he's not looking for symlinks resolved:
自我编辑,我只是注意到 OP 说他不是在寻找已解决的符号链接:
"But for the functions I've written I need paths that are absolute, but do not have their symlinks resolved."
“但是对于我编写的函数,我需要绝对路径,但没有解析它们的符号链接。”
So guess this isn't so apropos to his question after all. :)
所以猜测这毕竟不是他的问题。:)
Since I've run into this many times over the years, and this time around I needed a pure bash portable version that I could use on OSX and linux, I went ahead and wrote one:
由于这些年来我遇到过很多次,这一次我需要一个可以在 OSX 和 linux 上使用的纯 bash 便携式版本,我继续写了一个:
The living version lives here:
活版本住在这里:
https://github.com/keen99/shell-functions/tree/master/resolve_path
https://github.com/keen99/shell-functions/tree/master/resolve_path
but for the sake of SO, here's the current version (I feel it's well tested..but I'm open to feedback!)
但为了 SO,这是当前版本(我觉得它经过了很好的测试......但我愿意接受反馈!)
Might not be difficult to make it work for plain bourne shell (sh), but I didn't try...I like $FUNCNAME too much. :)
让它适用于普通的 bourne shell (sh) 可能并不难,但我没有尝试......我太喜欢 $FUNCNAME 了。:)
#!/bin/bash
resolve_path() {
#I'm bash only, please!
# usage: resolve_path <a file or directory>
# follows symlinks and relative paths, returns a full real path
#
local owd="$PWD"
#echo "$FUNCNAME for " >&2
local opath=""
local npath=""
local obase=$(basename "$opath")
local odir=$(dirname "$opath")
if [[ -L "$opath" ]]
then
#it's a link.
#file or directory, we want to cd into it's dir
cd $odir
#then extract where the link points.
npath=$(readlink "$obase")
#have to -L BEFORE we -f, because -f includes -L :(
if [[ -L $npath ]]
then
#the link points to another symlink, so go follow that.
resolve_path "$npath"
#and finish out early, we're done.
return $?
#done
elif [[ -f $npath ]]
#the link points to a file.
then
#get the dir for the new file
nbase=$(basename $npath)
npath=$(dirname $npath)
cd "$npath"
ndir=$(pwd -P)
retval=0
#done
elif [[ -d $npath ]]
then
#the link points to a directory.
cd "$npath"
ndir=$(pwd -P)
retval=0
#done
else
echo "$FUNCNAME: ERROR: unknown condition inside link!!" >&2
echo "opath [[ $opath ]]" >&2
echo "npath [[ $npath ]]" >&2
return 1
fi
else
if ! [[ -e "$opath" ]]
then
echo "$FUNCNAME: $opath: No such file or directory" >&2
return 1
#and break early
elif [[ -d "$opath" ]]
then
cd "$opath"
ndir=$(pwd -P)
retval=0
#done
elif [[ -f "$opath" ]]
then
cd $odir
ndir=$(pwd -P)
nbase=$(basename "$opath")
retval=0
#done
else
echo "$FUNCNAME: ERROR: unknown condition outside link!!" >&2
echo "opath [[ $opath ]]" >&2
return 1
fi
fi
#now assemble our output
echo -n "$ndir"
if [[ "x${nbase:=}" != "x" ]]
then
echo "/$nbase"
else
echo
fi
#now return to where we were
cd "$owd"
return $retval
}
here's a classic example, thanks to brew:
这是一个经典的例子,感谢 brew:
%% ls -l `which mvn`
lrwxr-xr-x 1 draistrick 502 29 Dec 17 10:50 /usr/local/bin/mvn@ -> ../Cellar/maven/3.2.3/bin/mvn
use this function and it will return the -real- path:
使用此函数,它将返回 -real- 路径:
%% cat test.sh
#!/bin/bash
. resolve_path.inc
echo
echo "relative symlinked path:"
which mvn
echo
echo "and the real path:"
resolve_path `which mvn`
%% test.sh
relative symlinked path:
/usr/local/bin/mvn
and the real path:
/usr/local/Cellar/maven/3.2.3/libexec/bin/mvn
回答by Mikey
This does the trick for me on OS X: $(cd SOME_DIRECTORY 2> /dev/null && pwd -P)
这在 OS X 上对我有用: $(cd SOME_DIRECTORY 2> /dev/null && pwd -P)
It should work anywhere. The other solutions seemed too complicated.
它应该可以在任何地方工作。其他解决方案似乎太复杂了。
回答by isapir
Use readlink -f <relative-path>
, e.g.
使用readlink -f <relative-path>
,例如
export FULLPATH=`readlink -f ./`
回答by cy8g3n
There's another method. You can use python embedding in bash script to resolve a relative path.
还有一种方法。您可以在 bash 脚本中使用 python 嵌入来解析相对路径。
abs_path=$(python3 - <<END
from pathlib import Path
path = str(Path("").expanduser().resolve())
print(path)
END
)