我想转换/foo/bar/../ foo
是否有bash命令可以做到这一点?
编辑:在我的实际案例中,目录确实存在。
我想转换/foo/bar/../ foo
是否有bash命令可以做到这一点?
编辑:在我的实际案例中,目录确实存在。
当前回答
我最近的解决方案是:
pushd foo/bar/..
dir=`pwd`
popd
根据蒂姆·惠特科姆的回答。
其他回答
我最近的解决方案是:
pushd foo/bar/..
dir=`pwd`
popd
根据蒂姆·惠特科姆的回答。
我需要一个同时满足这三点的解决方案:
在普通mac上工作。realpath和readlink -f是插件 解决符号链接 有错误处理
没有一个人的答案同时包含了第一条和第二条。我加了第三条是为了让其他人不用再剃牦牛了。
#!/bin/bash
P="${1?Specify a file path}"
[ -e "$P" ] || { echo "File does not exist: $P"; exit 1; }
while [ -h "$P" ] ; do
ls="$(ls -ld "$P")"
link="$(expr "$ls" : '.*-> \(.*\)$')"
expr "$link" : '/.*' > /dev/null &&
P="$link" ||
P="$(dirname "$P")/$link"
done
echo "$(cd "$(dirname "$P")"; pwd)/$(basename "$P")"
下面是一个简短的测试用例,在路径中有一些扭曲的空格,以充分练习引用
mkdir -p "/tmp/test/ first path "
mkdir -p "/tmp/test/ second path "
echo "hello" > "/tmp/test/ first path / red .txt "
ln -s "/tmp/test/ first path / red .txt " "/tmp/test/ second path / green .txt "
cd "/tmp/test/ second path "
fullpath " green .txt "
cat " green .txt "
如果您想要从路径中删除部分文件名,“dirname”和“basename”是您的朋友,“realpath”也很方便。
dirname /foo/bar/baz
# /foo/bar
basename /foo/bar/baz
# baz
dirname $( dirname /foo/bar/baz )
# /foo
realpath ../foo
# ../foo: No such file or directory
realpath /tmp/../tmp/../tmp
# /tmp
realpath替代品
如果您的shell不支持realpath,您可以尝试
readlink -f /path/here/..
Also
readlink -m /path/there/../../
工作原理与
realpath -s /path/here/../../
在这种情况下,路径不需要存在就可以被规范化。
我不知道是否有直接的bash命令可以做到这一点,但我通常会这样做
normalDir="`cd "${dirToNormalize}";pwd`"
echo "${normalDir}"
而且效果很好。
realpath试试。以下是全文来源,特此捐赠给公众领域。
// realpath.c: display the absolute path to a file or directory.
// Adam Liss, August, 2007
// This program is provided "as-is" to the public domain, without express or
// implied warranty, for any non-profit use, provided this notice is maintained.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <limits.h>
static char *s_pMyName;
void usage(void);
int main(int argc, char *argv[])
{
char
sPath[PATH_MAX];
s_pMyName = strdup(basename(argv[0]));
if (argc < 2)
usage();
printf("%s\n", realpath(argv[1], sPath));
return 0;
}
void usage(void)
{
fprintf(stderr, "usage: %s PATH\n", s_pMyName);
exit(1);
}