如何检索给定相对路径的绝对路径
是否有命令可以检索给定相对路径的绝对路径?
例如我希望 $line 包含 dir ./etc/
中每个文件的绝对路径
find ./ -type f | while read line; do
echo $line
done
Is there a command to retrieve the absolute path given a relative path?
For example I want $line to contain the absolute path of each file in dir ./etc/
find ./ -type f | while read line; do
echo $line
done
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(26)
尝试
真实路径
。要避免扩展符号链接,请使用
realpath -s
。答案来自“bash/fish 命令打印绝对路径文件路径”。
Try
realpath
.To avoid expanding symlinks, use
realpath -s
.The answer comes from "bash/fish command to print absolute path to a file".
如果您安装了 coreutils 软件包,通常可以使用 readlink -frelative_file_name 来检索绝对文件名(已解析所有符号链接)
If you have the coreutils package installed you can generally use
readlink -f relative_file_name
in order to retrieve the absolute one (with all symlinks resolved)UPD 一些解释
"$1"
dirname "$1"
cd "$(dirname "$1")
进入这个相对目录,并通过运行pwd 获取它的绝对路径
shell 命令$(basename "$1")
echo
它UPD Some explanations
"$1"
dirname "$1"
cd "$(dirname "$1")
into this relative dir and get absolute path for it by runningpwd
shell command$(basename "$1")
echo
it使用:
获取所有文件或
显示完整路径(如果相对路径很重要)
use:
to get all files or
to display full path (if relative path matters to)
不管怎样,我投票给了所选择的答案,但想分享一个解决方案。缺点是,它仅限于 Linux - 在进入 Stack Overflow 之前,我花了大约 5 分钟试图找到 OSX 的等效版本。我确信它就在那里。
在 Linux 上,您可以将
readlink -e
与dirname
结合使用。然后你使用
dirname 的姐妹
basename
来获取文件名
产生
把它们放在一起..
产生
如果你的目标是目录,那么你是安全的,
basename
不会返回任何内容你最终会在最终输出中得到双斜杠。
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.
On Linux you can use
readlink -e
in tandem withdirname
.yields
And then you use
dirname
's sister,basename
to just getthe filename
yields
Put it all together..
yields
You're safe if you're targeting a directory,
basename
will return nothingand you'll just end up with double slashes in the final output.
我认为这是最可移植的:
如果路径不存在,它将失败。
I think this is the most portable:
It will fail if the path does not exist though.
realpath 可能是最好的
但是......
最初的问题一开始就非常混乱,示例很差
与所述问题相关。
所选答案实际上回答了给出的示例,但根本不回答
标题中的问题。第一个命令就是答案(是吗?
真的 ?我怀疑),并且没有“/”也可以做到。我看不到
第二个命令正在做什么。
有几个问题是混合在一起的:
将相对路径名更改为绝对路径名,无论它是什么
表示,可能什么也没有。
(通常,如果您发出诸如
touch foo/bar
之类的命令,路径名
foo/bar
必须存在,并且可能用于在实际创建文件之前进行计算。)
可能有多个绝对路径名表示同一个文件
(或潜在文件),特别是因为符号链接(symlinks)
在路径上,但可能出于其他原因(设备可能是
以只读方式安装两次)。人们可能想也可能不想解决
明确这样的符号链接。
到达非符号链接的符号链接链的末尾
文件或名称。这可能会也可能不会产生绝对路径名,
取决于它是如何完成的。人们可能愿意,也可能不愿意
将其解析为绝对路径名。
不带选项的命令
readlink foo
仅在以下情况下给出答案参数
foo
是一个符号链接,答案就是它的值符号链接。没有其他链接被跟随。答案可能是相对路径:
无论符号链接参数的值是什么。
但是,
readlink
具有适用于所有内容的选项(-f -e 或 -m)文件,并给出一个绝对路径名(没有符号链接的路径名)
参数实际表示的文件。
这对于任何不是符号链接的东西都适用,尽管有人可能会这样做
希望使用绝对路径名而不解析中间路径
路径上的符号链接。这是通过命令
realpath -s foo
完成的。在符号链接参数的情况下,
readlink
及其选项将再次解析参数绝对路径上的所有符号链接,但是
它还将包括可能遇到的所有符号链接
跟随参数值。如果您想要一个,您可能不希望这样
参数符号链接本身的绝对路径,而不是任何内容的绝对路径
它可能链接到。同样,如果
foo
是符号链接,则realpath -s foo
将获取绝对路径而不解析符号链接,包括符号链接
作为参数给出。
如果没有
-s
选项,realpath
的作用与readlink
,除了简单的读取一个链接的值,还有几个其他事情。我只是不清楚为什么
readlink
有它的选项,显然造成了不受欢迎的冗余
真实路径。
探索网络就不多说了,除了可能有
不同系统之间存在一些差异。
结论:
realpath
是最好用的命令,使用最多灵活性,至少对于此处要求的使用而言。
realpath
is probably bestBut ...
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
, thepathname
foo/bar
must exist for you, and possibly be used incomputation, 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.
The command
readlink foo
without option gives an answer only if itsargument
foo
is a symbolic link, and that answer is the value of thatsymlink. No other link is followed. The answer may be a relative path:
whatever was the value of the symlink argument.
However,
readlink
has options (-f -e or -m) that will work for allfiles, and give one absolute pathname (the one with no symlinks) to
the file actually denoted by the argument.
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
In the case of a symlink argument,
readlink
with its options willagain 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
foo
is a symlink,realpath -s foo
willget an absolute path without resolving symlinks, including the one
given as argument.
Without the
-s
option,realpath
does pretty much the same asreadlink
, except for simply reading the value of a link, as well as severalother things. It is just not clear to me why
readlink
has itsoptions, creating apparently an undesirable redundancy with
realpath
.Exploring the web does not say much more, except that there may be
some variations across systems.
Conclusion :
realpath
is the best command to use, with the mostflexibility, at least for the use requested here.
我最喜欢的解决方案是@EugenKonkov 的这个,因为它并不意味着存在其他实用程序(coreutils 包)。
但相对路径“。”失败了。和“..”,所以这里是处理这些特殊情况的稍微改进的版本。
但是,如果用户没有 cd 权限进入相对路径的父目录,它仍然会失败。
My favourite solution was the one by @EugenKonkov because it didn't imply the presence of other utilities (the coreutils package).
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
cd
into the parent directory of the relative path, though.尤金的答案对我来说不太有效,但这确实有效:
旁注,您当前的工作目录不受影响。
Eugen's answer didn't quite work for me but this did:
Side note, your current working directory is unaffected.
恕我直言,最好的解决方案是在这里发布的:https://stackoverflow.com/a/3373298/9724628。
它确实需要 python 才能工作,但它似乎涵盖了所有或大部分边缘情况,并且是非常可移植的解决方案。
The best solution, imho, is the one posted here: 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.
对 @ernest-a 相当不错的版本的改进:
这可以正确处理路径最后一个元素是
..
的情况,在这种情况下"$(pwd)/$( @ernest-a 的答案中的 basename "$1")"
将显示为accurate_sub_path/spurious_subdirectory/..
。An improvement to @ernest-a's rather nice version:
This deals correctly with the case where the last element of the path is
..
, in which case the"$(pwd)/$(basename "$1")"
in @ernest-a's answer will come through asaccurate_sub_path/spurious_subdirectory/..
.对于
find
,最简单的方法可能是只给出要搜索的绝对路径,例如:In case of
find
, it's probably easiest to just give the absolute path for it to search in, e.g.:如果您在 Mac OS X 上使用 bash,既没有 realpath 存在,也没有 readlink 可以打印绝对路径,您可以选择编写自己的版本来打印它。
这是我的实现:
(纯 bash)
(使用 gawk)
(纯 bsd awk)
示例:
If you are using bash on Mac OS X which neither has realpath existed nor its readlink can print the absolute path, you may have choice but to code your own version to print it.
Here is my implementation:
(pure bash)
(use gawk)
(pure bsd awk)
example:
我发现Eugen Konkov的答案是最好的它不需要安装任何程序。但是,对于不存在的目录,它将失败。
我写了一个适用于不存在目录的函数:
它解决了不存在目录的问题,通过用
dirname
向上遍历,直到cd
成功,然后返回当前目录加上被dirname
删除的所有内容。I found Eugen Konkov's answer to be the best as it doesn't require installing any program. However, it will fail for non-existent directories.
I wrote a function that works for non-existent directories:
It solves the problem of non-existent directories by traversing up with
dirname
untilcd
succeeds, then returning the current directory plus everything that was removed bydirname
.与 @ernest-a 的答案类似,但不影响
$OLDPWD
或定义一个新函数,您可以触发子 shell(cd; pwd)
Similar to @ernest-a's answer but without affecting
$OLDPWD
or define a new function you could fire a subshell(cd <path>; pwd)
您可以对任何相对路径 $line 使用 bash 字符串替换:
基本的字符串前面替换遵循以下公式
${string/#substring/replacement}
这里讨论得很好: https://www.tldp.org/ LDP/abs/html/string-manipulation.html
当我们希望它成为我们查找/替换的字符串的一部分时,
\
字符会否定/
。You could use bash string substitution for any relative path $line:
The basic front-of-string substitution follows the formula
${string/#substring/replacement}
which is discussed well here: https://www.tldp.org/LDP/abs/html/string-manipulation.html
The
\
character negates the/
when we want it to be part of the string that we find/replace.我无法找到在 Mac OS Catalina、Ubuntu 16 和 Centos 7 之间完美移植的解决方案,因此我决定使用 python 内联来实现,它非常适合我的 bash 脚本。
I was unable to find a solution that was neatly portable between Mac OS Catalina, Ubuntu 16 and Centos 7, so I decided to do it with python inline and it worked well for my bash scripts.
BLUF:
这是符合 POSIX 标准的解释(我认为),所以它应该适用于任何平台。
当然,这是可以编写脚本的,但我认为将其分解可能会让某些人更容易理解/修改特定的用例。
您可以使用
which
、locate
、find
、完整路径等。x=your_file_name
file
轻松指示符号链接接下来,稍微整理一下输出,以便我们获得“完整”相对路径。
我们只需要删除这个例子中的中间部分。
注意大写 Y 与小写 x。可能有一种更干净的方法可以做到这一点。
使用
dirname
我们只得到路径部分。cd
到它,名称应该会自行清理。这引导我们使用古老的 UNIX 技巧,通过在括号/子 shell 中完成所有操作来“幽灵行走”目录。完成后,这实际上使我们返回到当前目录。
为了完整起见,我们可以将实际的文件名贴回末尾。
ls 甚至可以确保绝对路径有效,以获得奖励积分。
所以
/usr/local/bin/nvi
实际上是/usr/local/Cellar/nvi/1.81.6_5/bin/nvi
快速“转换”路径的简化示例:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/file .html
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname。 html
BLUF:
Here is an explanation that is POSIX compliant (I think), so it should work on any platform.
This is scriptable, of course, but I think breaking it down might make it easier for some people to understand / modify to a particular use case.
You can use
which
,locate
,find
, full paths, whatever.x=your_file_name
file
easily indicates symlinksNext, munge the output a bit so we get a "complete" relative path.
We just need to remove the middle part in this example.
Note UPPERCASE Y vs lowercase x. There is probably a cleaner way to do this.
Using
dirname
we get just the path portion.cd
to it and the name should clean itself up.That leads us to the old UNIX trick to "ghost walk" a directory by doing it all in parenthesis / a sub-shell. This effectively returns us to our current directory when done.
We can stick the actual file name back on the end for completeness.
ls
even makes sure the absolute path is valid, for bonus points.So
/usr/local/bin/nvi
is really/usr/local/Cellar/nvi/1.81.6_5/bin/nvi
Simplified example to quickly "convert" a path:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/file.html
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html
他们所说的,除了
find $PWD
或(在 bash 中)find ~+
更方便一些。What they said, except
find $PWD
or (in bash)find ~+
is a bit more convenient.如果相对路径是目录路径,那么试试我的,应该是最好的:
If the relative path is a directory path, then try mine, should be the best:
这是一个相当短的函数,可用于仅使用 POSIX shell 和 readlink 语义来完全绝对化和规范化任何给定的输入路径:
如果引用的文件不存在,则仅使用通向最终文件名的目录路径将会得到解决。如果通向文件路径的任何目录不存在,则会返回 cd 错误。这恰好是它试图模仿的 GNU/Linux
readlink -f
命令的确切语义。在 bash/zsh 中,您还可以将数字列表压缩为
{1..8}
或类似内容。选择 8 的数量是因为这是 Linux 多年来的最大限制,之后在版本 4.2 中将其更改为整个路径的 40 个分辨率的总限制。如果达到分辨率限制,代码不会失败,而是返回最后考虑的路径 - 可以添加显式的[ -L "${FILEPATH}" ]
检查来检测这个条件不过。通过简单地删除函数和子 shell 包装器,此代码还可以轻松地重用,以确保当前工作目录与文件系统中执行的脚本的位置匹配(shell 脚本的常见要求):
Here's a rather short function that can be used to fully absolutize and canonicalize any given input path using only POSIX shell and
readlink
semantics:If the referenced file does not exist only the directory path leading up to the final filename will be resolved. If the any of the directories leading up to the file path does not exist a
cd
error will be returned. This happens to be the exact semantics of the GNU/Linuxreadlink -f
command it tries to mimic.In bash/zsh you can also compact the list of numbers to just
{1..8}
or similar. The number of 8 was chosen as this was maximum limit in Linux for many years before the changed it a total limit of 40 resolution for the entire path in version 4.2. If the resolution limit is reached the code will not fail, but instead return last considered path instead – an explicit[ -L "${FILEPATH}" ]
check could be added to detect this condition however.This code can also be easily reused for ensuring the current working directory matches the executed script's location in the filesystem (a common requirement for shell scripts), by simply removing the function and subshell wrapper:
在上面的代码片段中,awk 用于分割从 echo (通过管道)接收到的目录字符串并创建一个数组。
以下是所发生情况的分步列表:
使用 cd 移动到每个目录,然后打印 $PWD 的值是让操作系统确定绝对路径的好方法
In the snippet above awk is used to split the string of directories received from echo (via the pipeline) and creates an array.
Here is a step-by-step list of what is happening:
Using cd to travel to each directory and then print the value of $PWD is a great way to have the OS do the work of determining an absolute path
如果您想将包含相对路径的变量转换为绝对路径,则可以这样做:
“cd”会在不更改工作目录的情况下进行回显,因为在子 shell 中执行。
If you want to transform a variable containing a relative path into an absolute one, this works :
"cd" echoes without changing the working directory, because executed here in a sub-shell.
这是来自所有其他解决方案的链式解决方案,例如,当
realpath
失败时,要么因为未安装,要么因为它以错误代码退出,然后尝试下一个解决方案,直到获得正确的路径。This is a chained solution from all others, for example, when
realpath
fails, either because it is not installed or because it exits with error code, then, the next solution is attempted until it get the path right.基于此答案,作者:@EugenKonkov 和 此答案,作者:@HashChange,我的回答结合了前者的简洁性和后者对
.
和..
的处理。我相信下面的所有选项都依赖于基本的 Shell 命令语言 POSIX标准。使用
dirname
和basename
,一个选项是:如果不使用
dirname
或basename
,另一个简短的选项是:我会推荐上面两个选项之一,其余的只是为了好玩...
Grep 版本:
作为“使用 shell 的有限正则表达式可以做什么”的有趣示例:
Based on this answer by @EugenKonkov and this answer by @HashChange, my answer combines the brevity of the former with the handling of
.
and..
of the latter. I believe that all the options below rely upon nothing more than the basic Shell Command Language POSIX standards.Using
dirname
andbasename
, an option is:Without using
dirname
orbasename
, another brief option is:I would recommend one of the two options above, the rest are just for fun...
Grep version:
As an interesting example of "what can be done with the shell's limited RegEx":
更新之前的答案
使用 python 3允许
An update on previous answer using python 3
Allowing