【问题标题】:bash equivalent of Python's os.path.normpath?bash 相当于 Python 的 os.path.normpath?
【发布时间】:2011-09-17 14:38:19
【问题描述】:

bash 相当于os.path.normpath 是什么?具体来说,我有兴趣删除执行find 时给出的前导./

matt@stanley:~/src/libtelnet-0.20/test$ 查找
.
./Makefile
./Makefile.in
./Makefile.am
...

【问题讨论】:

  • 出于好奇,为什么? ./foo 工作正常,所以程序不应该关心...
  • ./Makefile 不是绝对路径名,因此您可以毫无问题地使用它。那里。问题解决了。
  • @Nemo:规范化路径用于清单文件。否则根本不是问题。

标签: python bash path find normalization


【解决方案1】:

好吧,为此,您可以简单地通过sed 管道输出,您不必规范化整个路径:

your_command_goes_here | sed 's?^\./??'

这将删除行首的所有./ 序列。

以下记录显示了这一点:

pax$ find -name 'qq*sh'
./qq.ksh
./qq.sh
./qq.zsh
./qq2.sh
./qq2.zsh
./qqq/qq.sh

pax$ find -name 'qq*sh' | sed 's?^./??'
qq.ksh
qq.sh
qq.zsh
qq2.sh
qq2.zsh
qqq/qq.sh

如您所见,我的临时 shell 脚本有一个相当直观的命名标准 :-)

【讨论】:

    【解决方案2】:

    我正在努力寻找一个我想使用os.path.normpath 的案例。在具有符号链接的系统上,例如 unix 或 Windows,它返回的值可能不会指定同一个文件:

    $ mkdir /tmp/one /tmp/one/two
    $ ln -s /tmp/one/two /tmp/foo
    $ python -c 'import os.path; print os.path.normpath("/tmp/foo/..")'
    /tmp
    $ ls /tmp/foo/..
    two
    

    /tmp/foo/../tmp/one,而不是 /tmp

    在 Linux 上,readlink -- "$filename" 规范化路径中的所有符号链接。它返回的文件名在命令执行时指定与$filename 相同的文件(如果涉及的符号链接之一被更改,它可能不会在以后)。但大多数时候,这不是必需的:保持 $filename 不变即可。

    如果您出于美观原因想要删除 ./ 前缀,只需将其删除即可。

    filename=${filename#./}
    find | sed -e 's!^\./!!'
    

    【讨论】:

    • 在清单文件中使用规范化路径。它们不能是绝对的。
    【解决方案3】:

    我通常使用find-printf 参数来做到这一点。

    如果您在多个路径中搜索,以下方法可以正常工作:

    find path1 path2
    

    如果您在 . 中搜索,以下内容可以正常工作:

    find -printf '%P\n'
    

    如果您有混合路径(例如find path1 path2 .),则必须使用sed

    【讨论】:

    • 我不确定你所说的混合路径是什么意思,它似乎可以在没有它的情况下找到。
    【解决方案4】:

    怎么样:

    newpath=`echo -n "$oldpath" | python -c 'import sys, os; print os.path.normpath(sys.stdin.readline())'`
    

    ?

    我认为没有任何内置的 bash 函数可以完成 Python 的 normpath 所做的一切。您最好准确地描述您想要执行的转换。

    【讨论】:

    • 遗憾打印在 2 和 3 之间切换行为 :)
    【解决方案5】:

    这样写:

    normpath() {
        [[ -z "$1" ]] && return
    
        local skip=0 p o c
    
        p="$1"
        # check if we have absolute path and if not make it absolute
        [[ "${p:0:1}" != "/" ]] && p="$PWD/$p"
    
        o=""
        # loop on processing all path elements
        while [[ "$p" != "/" ]]; do
            # retrive current path element
            c="$(basename "$p")"
            # shink our path on one(current) element
            p="$(dirname "$p")"
    
            # basename/dirname correct handle multimple "/" chars
            # so we can not warry about them
    
            # skip elements "/./" 
            [[ "$c" == "." ]] && continue
            if [[ "$c" == ".." ]]; then
                # if we have point on parent dir, we must skip next element
                # in other words "a/abc/../c" must become "a/c"
                let "skip += 1"
            elif [[ 0 -lt $skip ]]; then
                # skip current element and decrease skip counter
                let "skip -= 1"
            else
                # this is normal element and we must add it to result
                [[ -n "$o" ]] && o="/$o"
                o="$c$o"
            fi
        done
    
        # last thing - restore original absolute path sign
        echo "/$o"
    }
    

    【讨论】:

    • 我添加了一些 cmets。为了不进行绝对路径“清理”,我们应该更改循环条件并在路径高于其起点时添加句柄(添加所需的计数“../”元素)
    【解决方案6】:

    可能重复here。但是,如果您只是对剥离前导 ./ 感兴趣,则可以这样做

    find -type f | sed 's/^\.\///'
    

    【讨论】:

    • @Matt,有趣的是,我已经逃脱了。但是选择了一些格式 > 没有正确显示。我现在选择预格式化,它会显示
    【解决方案7】:

    我找到了:它叫realpath! 输入类似:

    realpath ..   # the most interesting thing
    

    realpath .    # equivalent to `pwd' and to `echo $PWD'
    

    享受吧!

    os.path.normpath 不同,realpath 需要路径存在。如果只是想规范化为字符串realpath -m可以使用。

    【讨论】:

    • 会很好,但它不标准。
    猜你喜欢
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 2022-11-10
    • 2021-07-15
    • 2011-12-09
    • 2023-02-02
    • 1970-01-01
    • 2016-05-08
    相关资源
    最近更新 更多