Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何检索给定相对路径的绝对路径_Bash_Shell_Path_Absolute - Fatal编程技术网

Bash 如何检索给定相对路径的绝对路径

Bash 如何检索给定相对路径的绝对路径,bash,shell,path,absolute,Bash,Shell,Path,Absolute,在给定相对路径的情况下,是否有检索绝对路径的命令 例如,我希望$line包含dir/etc/中每个文件的绝对路径 find ./ -type f | while read line; do echo $line done 对于find,最简单的方法可能是只给出它要搜索的绝对路径,例如: find /etc find `pwd`/subdir_of_current_dir/ -type f 使用: 获取所有文件或 echo "$(pwd)/$line" 显示完整路径

在给定相对路径的情况下,是否有检索绝对路径的命令

例如,我希望$line包含dir
/etc/
中每个文件的绝对路径

find ./ -type f | while read line; do
   echo $line
done

对于
find
,最简单的方法可能是只给出它要搜索的绝对路径,例如:

find /etc
find `pwd`/subdir_of_current_dir/ -type f
使用:

获取所有文件或

echo "$(pwd)/$line"

显示完整路径(如果相对路径与之相关)

他们所说的,除了
find$PWD
或(在bash中)
find~+
更方便一些。

如果您安装了coreutils包,您通常可以使用
readlink-f relative\u file\u name
来检索绝对路径(所有符号链接都已解析)

为了它的价值,我投票赞成选出的答案,但想分享一个解决方案。缺点是,它仅限于Linux—在谈到堆栈溢出之前,我花了大约5分钟的时间试图找到OSX的等价物。我相信它就在那里

在Linux上,您可以将
readlink-e
dirname
结合使用

$(dirname $(readlink -e ../../../../etc/passwd))
屈服

/etc/
/etc/passwd
然后使用
dirname
的妹妹
basename
来获取 文件名

$(basename ../../../../../passwd)
屈服

passwd
把它们放在一起

F=../../../../../etc/passwd
echo "$(dirname $(readlink -e $F))/$(basename $F)"
屈服

/etc/
/etc/passwd
如果目标目录是安全的,
basename
将不返回任何内容
最终的输出结果是双斜杠。

试试
realpath

~ $ sudo apt-get install realpath  # may already be installed
~ $ realpath .bashrc
/home/username/.bashrc
要避免扩展符号链接,请使用
realpath-s


答案来自“

realpath可能是最好的

但是

最初的问题一开始就非常混乱,举了一个很糟糕的例子 与上述问题有关

所选答案实际上回答了给出的示例,而不是全部 标题中的问题。第一个命令就是这个答案(是吗 真的吗?我怀疑),没有“/”也能做得很好。我看不见 第二个命令正在做什么

有几个问题是复杂的:

  • 将相对路径名更改为绝对路径名 表示,可能什么都没有。 (通常,如果发出命令,如
    touch foo/bar
    ,则 路径名
    foo/bar
    必须为您存在,并且可能在中使用 计算,在实际创建文件之前。)

  • 可能有多个绝对路径名表示同一文件 (或潜在文件),特别是因为符号链接(符号链接) 在路径上,但可能是由于其他原因(设备可能 安装两次(只读)。一个人可能想也可能不想解决 明确此类符号链接

  • 到达非符号链接的符号链接链的末尾 文件或名称。这可能会也可能不会产生绝对路径名, 这取决于它是如何完成的。一个人可能想,也可能不想 将其解析为绝对路径名

命令
readlink foo
without选项仅在其 参数
foo
是一个符号链接,这个答案就是它的值 符号链接。没有其他链接。答案可能是相对路径: 符号链接参数的值是多少

但是,
readlink
有一些选项(-f-e或-m)适用于所有人 文件,并为其指定一个绝对路径名(不带符号链接的路径名) 实际由参数表示的文件

这对于任何不是符号链接的东西都很好,尽管有人可能会这样做 希望使用绝对路径名而不解析中间路径 路径上的符号链接。这是通过命令
realpath-sfoo

对于符号链接参数,
readlink
及其选项将 再次解析参数绝对路径上的所有符号链接,但 这还将包括可能遇到的所有符号链接 在参数值之后。如果你想要一份工作,你可能不想要 参数符号链接本身的绝对路径,而不是指向任何对象 它可能链接到。同样,如果
foo
是一个符号链接,
realpath-sfoo
将 获取绝对路径而不解析符号链接,包括 作为论据给出

没有
-s
选项,
realpath
readlink
,除了简单地读取一个链接的值,还有几个 其他事情。我只是不清楚为什么
readlink
有它自己的功能 选项,显然造成了不必要的冗余
realpath

探索网络并不能说明更多,除了可能有 系统之间存在一些差异

结论:
realpath
是使用的最佳命令,具有最大的可用性
灵活性,至少适用于此处要求的使用。

我认为这是最便携的:

abspath() {                                               
    cd "$(dirname "$1")"
    printf "%s/%s\n" "$(pwd)" "$(basename "$1")"
    cd "$OLDPWD"
}

如果路径不存在,则会失败。

如果您在Mac OS X上使用的bash既不存在realpath,也不存在其readlink可以打印绝对路径,您可以选择,但可以编写自己的版本来打印它。 以下是我的实现:

(纯bash)

(用呆呆的眼神)


与@ernest-a的答案类似,但在不影响
$OLDPWD
或定义新函数的情况下,您可以启动子shell
(cd;pwd)

UPD一些解释

  • 此脚本获取相对路径作为参数
    “$1”
  • 然后我们得到该路径的dirname部分(您可以将dir或file传递给该脚本):
    dirname“$1”
  • 然后我们
    cd“$(dirname“$1”)
    进入这个相对目录,并通过运行
    pwd
    shell命令获得它的绝对路径
  • 之后,我们将basename附加到绝对路径:
    $(basename“$1”)
  • 作为最后一步,我们
    echo
    it

  • 如果相对路径是目录路径,请尝试使用我的,应该是最好的:

    absPath=$(pushd ../SOME_RELATIVE_PATH_TO_Directory > /dev/null && pwd && popd > /dev/null)
    
    echo $absPath
    

    如果要将包含相对路径的变量转换为绝对路径,可以执行以下操作:

       dir=`cd "$dir"`
    
    “cd”回声不带ch
    $ abspath I/am/.//..//the/./god/../of///.././war
    /Users/leon/I/the/war
    
    $ pwd
    /etc/apache2
    $ cd ../cups 
    $ cd -
    /etc/apache2
    $ (cd ~/..; pwd)
    /Users
    $ cd -
    /etc/cups
    
    #! /bin/sh
    echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
    
    absPath=$(pushd ../SOME_RELATIVE_PATH_TO_Directory > /dev/null && pwd && popd > /dev/null)
    
    echo $absPath
    
    echo "mydir/doc/ mydir/usoe ./mydir/usm" |  awk '{ split($0,array," "); for(i in array){ system("cd "array[i]" && echo $PWD") } }'
    
       dir=`cd "$dir"`
    
        absolute="$(cd $(dirname \"$file\"); pwd)/$(basename \"$file\")"
    
    #! /bin/sh
    
    # Takes a path argument and returns it as an absolute path. 
    # No-op if the path is already absolute.
    function to-abs-path {
        local target="$1"
    
        if [ "$target" == "." ]; then
            echo "$(pwd)"
        elif [ "$target" == ".." ]; then
            echo "$(dirname "$(pwd)")"
        else
            echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
        fi
    }
    
    line=$(echo ${line/#..\//`cd ..; pwd`\/})
    line=$(echo ${line/#.\//`pwd`\/})
    echo $line
    
    to_abs_path() {
      python -c "import os; print os.path.abspath('$1')"
    }
    
    to_abs_path "/some_path/../secrets"
    
    function getRealPath()
    {
        local -i traversals=0
        currentDir="$1"
        basename=''
        while :; do
            [[ "$currentDir" == '.' ]] && { echo "$1"; return 1; }
            [[ $traversals -eq 0 ]] && pwd=$(cd "$currentDir" 2>&1 && pwd) && { echo "$pwd/$basename"; return 0; }
            currentBasename="$(basename "$currentDir")"
            currentDir="$(dirname "$currentDir")"
            [[ "$currentBasename" == '..' ]] && (( ++traversals )) || { [[ traversals -gt 0 ]] && (( traversals-- )) || basename="$currentBasename/$basename"; }
        done
    }
    
    absPathDirname()
    {
        [ -d "${1}" ] && set -- "${1}" || set -- "`dirname "${1}"`" "/`basename "${1}"`"
        echo "`cd "${1}"; pwd`${2}";
    }
    
    absPathMinusD()
    {
        [ -d "${1}" ] && set -- "${1}" || set -- "${1%${1##*/}}" "/${1##*/}"
        echo "`cd "${1:-.}"; pwd`${2}";
    }
    
    absPathGrep()
    {
        echo "`[ "${1##/*}" ] && echo "$1" | grep -Eo '^(.*/)?\.\.($|/)' | { read d && cd "$d"; echo "${PWD}/${1#$d}"; } || echo "$1"`"
    }
    
    absPathShellReplace()
    {
        E="${1##*/}"; D="${E#$E${E#.}}"; DD="${D#$D${D#..}}"
        DIR="${1%$E}${E#$DD}"; FILE="${1#$DIR}"; SEP=${FILE:+/}
        echo "`cd "${DIR:-.}"; pwd`${SEP#$DIR}$FILE"
    }