作为我的脚本的参数,有一些文件路径。这些当然可以是相对的(或包含〜)。但是对于我编写的功能,我需要绝对的路径,但没有解析其符号链接。
有什么功能吗?
作为我的脚本的参数,有一些文件路径。这些当然可以是相对的(或包含〜)。但是对于我编写的功能,我需要绝对的路径,但没有解析其符号链接。
有什么功能吗?
readlink
解决符号链接;OP不想这么做。
echo $(cd some_directory && pwd)
,不解析符号链接,如果some_directory不存在,则失败。工作目录不受影响。或分配给变量MY_PATH=$(cd some_directory && pwd)
。
Answers:
MY_PATH=$(readlink -f $YOUR_ARG)
将解析相对路径,例如"./"
和"../"
也考虑一下(来源):
#!/bin/bash
dir_resolve()
{
cd "$1" 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 \"$1\"`"
then
echo "$1 resolves to $abs_path"
echo pwd: `pwd` # function forks subshell, so working directory outside function is not affected
else
echo "Could not reach $1"
fi
man pwd
:“-P显示物理当前工作目录(所有符号链接解决)”,只是删除-P
function abspath {
if [[ -d "$1" ]]
then
pushd "$1" >/dev/null
pwd
popd >/dev/null
elif [[ -e "$1" ]]
then
pushd "$(dirname "$1")" >/dev/null
echo "$(pwd)/$(basename "$1")"
popd >/dev/null
else
echo "$1" does not exist! >&2
return 127
fi
}
使用pushd
/popd
进入一种pwd
有用的状态。
DIRSTACK
仅此而已。不错的解决方案!
sh
兼容性时,pushd; cd <dir>; <cmd>; popd
可以用代替(cd <dir>; <cmd>)
。
简单的一线:
function abs_path {
(cd "$(dirname '$1')" &>/dev/null && printf "%s/%s" "$PWD" "${1##*/}")
}
用法:
function do_something {
local file=$(abs_path $1)
printf "Absolute path to %s: %s\n" "$1" "$file"
}
do_something $HOME/path/to/some\ where
我仍在尝试弄清楚如何完全忽略该路径是否存在(因此也可以在创建文件时使用它)。
cd -
之后我应该重设吗?
${1##*/}
有basename
,虽然,没有把它在一个单独的变量,用空格的路径不能正常工作。
$PWD
,并通过运行它,它应该工作得很好:github.com/andsens/homeshick/blob/...
在OS X上,您可以使用
stat -f "%N" YOUR_PATH
在Linux上,您可能具有realpath
可执行文件。如果没有,以下方法可能会起作用(不仅适用于链接):
readlink -c YOUR_PATH
stat -f "%N" PATH
给我完全一样的路径
自我编辑,我只是注意到OP表示他不寻找已解决的符号链接:
“但是对于我编写的功能,我需要绝对的路径,但是没有解析它们的符号链接。”
因此,猜想这毕竟与他的问题不太相符。:)
多年来,由于我经历了很多次,并且这次我需要一个可以在OSX和linux上使用的纯bash便携式版本,因此我继续写了一个:
实际版本位于此处:
https://github.com/keen99/shell-functions/tree/master/resolve_path
但出于SO的缘故,这是当前版本(我觉得它已经过良好的测试..但我愿意接受反馈!)
使它适用于纯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 $1" >&2
local opath="$1"
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
}
这是一个经典的例子,感谢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
使用此函数,它将返回-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
您是否必须专门使用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";
}
?>
我知道这不是一个很好的解决方案,但确实可以。