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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4175264/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 19:52:41  来源:igfitidea点击:

How to retrieve absolute path given relative

bashshellpathabsolute

提问by nubme

Is there a command to retrieve the absolute path given the relative path?

是否有命令可以检索给定相对路径的绝对路径?

For example I want $line to contain the absolute path of each file in dir ./etc/

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

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

采纳答案by mpapis

use:

用:

find $(pwd)/ -type f

to get all files or

获取所有文件或

echo $(pwd)/$line

to display full path (if relative path matters to)

显示完整路径(如果相对路径很重要)

回答by epere4

Try realpath.

试试realpath

~ $ sudo apt-get install realpath  # may already be installed
~ $ realpath .bashrc
/home/username/.bashrc

To avoid expanding symlinks, use realpath -s.

为避免扩展符号链接,请使用realpath -s.

The answer comes from "bash/fish command to print absolute path to a file".

答案来自“用于打印文件绝对路径的 bash/fish 命令”。

回答by Moritz Bunkus

If you have the coreutils package installed you can generally use readlink -f relative_file_namein order to retrieve the absolute one (with all symlinks resolved)

如果您安装了 coreutils 软件包,您通常可以使用readlink -f relative_file_name它来检索绝对软件包(已解析所有符号链接)

回答by Eugen Konkov

#! /bin/sh
echo "$(cd "$(dirname "")"; pwd)/$(basename "")"

UPDSome explanations

UPD一些解释

  1. This script get relative path as argument "$1"
  2. Then we get dirnamepart of that path (you can pass either dir or file to this script): dirname "$1"
  3. Then we cd "$(dirname "$1")into this relative dir and get absolute path for it by running pwdshell command
  4. After that we append basenameto absolute path: $(basename "$1")
  5. As final step we echoit
  1. 此脚本获取相对路径作为参数 "$1"
  2. 然后我们获得该路径的dirname部分(您可以将 dir 或 file 传递给该脚本):dirname "$1"
  3. 然后我们cd "$(dirname "$1")进入这个相对目录并通过运行pwdshell 命令获取它的绝对路径
  4. 之后,我们将basename附加到绝对路径:$(basename "$1")
  5. 作为最后一步,我们echo

回答by synthesizerpatel

For what it's worth, I voted for the answer that was picked, but wanted to share a solution. The downside is, it's Linux only - I spent about 5 minutes trying to find the OSX equivalent before coming to Stack overflow. I'm sure it's out there though.

对于它的价值,我投票支持选择的答案,但想分享一个解决方案。缺点是,它仅适用于 Linux - 在堆栈溢出之前,我花了大约 5 分钟试图找到 OSX 等效项。不过我确定它就在那里。

On Linux you can use readlink -ein tandem with dirname.

在 Linux 上,您可以readlink -edirname.

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

yields

产量

/etc/

And then you use dirname's sister, basenameto just get the filename

然后你使用dirname's'sister,basename来获取文件名

$(basename ../../../../../passwd)

yields

产量

passwd

Put it all together..

全部放在一起..

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

yields

产量

/etc/passwd

You're safe if you're targeting a directory, basenamewill return nothing and you'll just end up with double slashes in the final output.

如果您的目标是目录,那么您是安全的,basename不会返回任何内容,并且最终输出中只会出现双斜杠。

回答by Ernest A

I think this is the most portable:

我认为这是最便携的:

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

It will fail if the path does not exist though.

如果路径不存在,它将失败。

回答by babou

realpathis probably best

realpath可能是最好的

But ...

但 ...

The initial question was very confused to start with, with an example poorly related to the question as stated.

最初的问题一开始就很困惑,有一个与所述问题关系不大的例子。

The selected answer actually answers the example given, and not at all the question in the title. The first command is that answer (is it really ? I doubt), and could do as well without the '/'. And I fail to see what the second command is doing.

所选答案实际上回答了给出的示例,而不是标题中的问题。第一个命令就是那个答案(真的吗?我怀疑),并且没有“/”也可以。而且我看不到第二个命令在做什么。

Several issues are mixed :

几个问题是混合的:

  • changing a relative pathname into an absolute one, whatever it denotes, possibly nothing. (Typically, if you issue a command such as touch foo/bar, the pathname foo/barmust exist for you, and possibly be used in computation, before the file is actually created.)

  • there may be several absolute pathname that denote the same file (or potential file), notably because of symbolic links (symlinks) on the path, but possibly for other reasons (a device may be mounted twice as read-only). One may or may not want to resolve explicity such symlinks.

  • getting to the end of a chain of symbolic links to a non-symlink file or name. This may or may not yield an absolute path name, depending on how it is done. And one may, or may not want to resolve it into an absolute pathname.

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

  • 可能有多个绝对路径名表示同一个文件(或潜在文件),主要是因为路径上的符号链接(符号链接),但也可能是其他原因(设备可能以只读方式挂载两次)。人们可能希望也可能不想明确解析此类符号链接。

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

The command readlink foowithout option gives an answer only if its argument foois a symbolic link, and that answer is the value of that symlink. No other link is followed. The answer may be a relative path: whatever was the value of the symlink argument.

readlink foo不带选项的命令仅在其参数foo是符号链接时才给出答案,并且该答案是该符号链接的值。没有遵循其他链接。答案可能是一个相对路径:无论符号链接参数的值是什么。

However, readlinkhas options (-f -e or -m) that will work for all files, and give one absolute pathname (the one with no symlinks) to the file actually denoted by the argument.

但是,readlink具有适用于所有文件的选项(-f -e 或 -m),并为参数实际表示的文件提供一个绝对路径名(没有符号链接的路径名)。

This works fine for anything that is not a symlink, though one might desire to use an absolute pathname without resolving the intermediate symlinks on the path. This is done by the command realpath -s foo

这适用于任何不是符号链接的内容,尽管人们可能希望使用绝对路径名而不解析路径上的中间符号链接。这是由命令完成的realpath -s foo

In the case of a symlink argument, readlinkwith its options will again resolve all symlinks on the absolute path to the argument, but that will also include all symlinks that may be encountered by following the argument value. You may not want that if you desired an absolute path to the argument symlink itself, rather than to whatever it may link to. Again, if foois a symlink, realpath -s foowill get an absolute path without resolving symlinks, including the one given as argument.

在符号链接参数的情况下,readlink其选项将再次解析参数绝对路径上的所有符号链接,但这也将包括跟随参数值可能遇到的所有符号链接。如果您想要参数符号链接本身的绝对路径,而不是它可能链接到的任何内容,则您可能不希望这样做。同样,如果foo是一个符号链接,realpath -s foo将获得一个不解析符号链接的绝对路径,包括作为参数给出的那个。

Without the -soption, realpathdoes pretty much the same as readlink, except for simply reading the value of a link, as well as several other things. It is just not clear to me why readlinkhas its options, creating apparently an undesirable redundancy with realpath.

如果没有这个-s选项,除了简单地读取链接的值以及其他一些事情之外,realpath它的作用与 几乎相同 readlink。我不清楚为什么readlink有它的选择,显然会产生不受欢迎的冗余 realpath

Exploring the web does not say much more, except that there may be some variations across systems.

探索网络并没有说更多,只是不同系统之间可能存在一些差异。

Conclusion : realpathis the best command to use, with the most flexibility, at least for the use requested here.

结论 :realpath是最好的命令,具有最大的灵活性,至少对于此处要求的使用而言。

回答by hashchange

My favourite solution was the oneby @EugenKonkov because it didn't imply the presence of other utilities (the coreutils package).

我最喜欢的解决方案是一个由@EugenKonkov,因为它并不意味着其他公用事业存在(的coreutils软件包)。

But it failed for the relative paths "." and "..", so here is a slightly improved version handling these special cases.

但是相对路径“.”失败了。和“..”,所以这里有一个处理这些特殊情况的稍微改进的版本。

It still fails if the user doesn't have the permission to cdinto the parent directory of the relative path, though.

但是,如果用户没有cd进入相对路径的父目录的权限,它仍然会失败。

#! /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=""

    if [ "$target" == "." ]; then
        echo "$(pwd)"
    elif [ "$target" == ".." ]; then
        echo "$(dirname "$(pwd)")"
    else
        echo "$(cd "$(dirname "")"; pwd)/$(basename "")"
    fi
}

回答by biomiker

Eugen's answer didn't quite work for me but this did:

欧根的回答对我来说不太适用,但这确实适用:

    absolute="$(cd $(dirname \"$file\"); pwd)/$(basename \"$file\")"

Side note, your current working directory is unaffected.

旁注,您当前的工作目录不受影响。

回答by MrSegFaulty

The best solution, imho, is the one posted here: https://stackoverflow.com/a/3373298/9724628.

最好的解决方案,恕我直言,是在这里发布的:https: //stackoverflow.com/a/3373298/9724628

It does require python to work, but it seems to cover all or most of the edge cases and be very portable solution.

它确实需要 python 才能工作,但它似乎涵盖了所有或大部分的边缘情况,并且是非常便携的解决方案。

  1. With resolving symlinks:
  1. 通过解析符号链接:
python -c "import os,sys; print(os.path.realpath(sys.argv[1]))" path/to/file
  1. or without it:
  1. 或没有它:
python -c "import os,sys; print(os.path.abspath(sys.argv[1]))" path/to/file