我想转换/foo/bar/../ foo

是否有bash命令可以做到这一点?


编辑:在我的实际案例中,目录确实存在。


当前回答

话多,回答有点晚。我需要写一个,因为我卡住了旧的RHEL4/5。 I处理绝对和相对链接,并简化//,/。/和somedir/../条目。

test -x /usr/bin/readlink || readlink () {
        echo $(/bin/ls -l $1 | /bin/cut -d'>' -f 2)
    }


test -x /usr/bin/realpath || realpath () {
    local PATH=/bin:/usr/bin
    local inputpath=$1
    local changemade=1
    while [ $changemade -ne 0 ]
    do
        changemade=0
        local realpath=""
        local token=
        for token in ${inputpath//\// }
        do 
            case $token in
            ""|".") # noop
                ;;
            "..") # up one directory
                changemade=1
                realpath=$(dirname $realpath)
                ;;
            *)
                if [ -h $realpath/$token ] 
                then
                    changemade=1
                    target=`readlink $realpath/$token`
                    if [ "${target:0:1}" = '/' ]
                    then
                        realpath=$target
                    else
                        realpath="$realpath/$target"
                    fi
                else
                    realpath="$realpath/$token"
                fi
                ;;
            esac
        done
        inputpath=$realpath
    done
    echo $realpath
}

mkdir -p /tmp/bar
(cd /tmp ; ln -s /tmp/bar foo; ln -s ../.././usr /tmp/bar/link2usr)
echo `realpath /tmp/foo`

其他回答

试试我们新的Bash库产品realpath-lib吧,我们已经把它放在GitHub上了,可以免费、不受阻碍地使用。它有完整的文档,是一个很好的学习工具。

它可以解析本地、相对和绝对路径,除了Bash 4+,它没有任何依赖关系;所以它应该适用于任何地方。它是免费的,干净的,简单的和有教育意义的。

你可以:

get_realpath <absolute|relative|symlink|local file path>

这个函数是库的核心:

function get_realpath() {

if [[ -f "$1" ]]
then 
    # file *must* exist
    if cd "$(echo "${1%/*}")" &>/dev/null
    then 
        # file *may* not be local
        # exception is ./file.ext
        # try 'cd .; cd -;' *works!*
        local tmppwd="$PWD"
        cd - &>/dev/null
    else 
        # file *must* be local
        local tmppwd="$PWD"
    fi
else 
    # file *cannot* exist
    return 1 # failure
fi

# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success

}

它还包含get_dirname, get_filename, get_ stemname和validate_path函数。在不同平台上尝试它,并帮助改进它。

今天我发现可以使用stat命令来解析路径。

对于"~/Documents"这样的目录:

你可以运行这个:

stat -f %N ~/文档

获取完整路径:

/用户/我/文档

对于符号链接,你可以使用%Y格式选项:

stat -f %Y example_symlink

这可能会返回如下结果:

/usr/local/sbin/example_symlink

格式选项可能在*NIX的其他版本上有所不同,但这些在OSX上对我有用。

一个使用node.js的简单解决方案:

#!/usr/bin/env node
process.stdout.write(require('path').resolve(process.argv[2]));

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);
}

我不知道是否有直接的bash命令可以做到这一点,但我通常会这样做

normalDir="`cd "${dirToNormalize}";pwd`"
echo "${normalDir}"

而且效果很好。