文件URI方案和相对文件

107
假设URI方案为“file”。同时假设路径以“.”开头。
一个示例路径是'./.bashrc'。完整的URI是什么样子?对我来说,'file://./.bashrc'看起来很奇怪。

3
根据维基百科(http://zh.wikipedia.org/wiki/统一资源标识符),当你相对地引用时,似乎可以省略方案并将“./.bashrc”作为 URI。但这只是一个猜测,我不确定它是否真的有效。 - Tony
2
@Tony - 谢谢,这对于在.docx文件中制作相对引用非常有效 - 只需解压缩,找到“file:///long-absolute-path/relative-path”引用,并替换为“relative-path”。 - tucuxi
1
严格省略前缀并不总是有效的,因为URI可能会使用百分号编码特殊字符(例如%20表示空格);根据应用程序,您可能需要将转义字符替换为其实际表示。 - sleblanc
Chromium 将很快失去 file:// 支持。https://bugs.chromium.org/p/chromium/issues/detail?id=1299624 - 9pfs
8个回答

102
简而言之,文件URL的格式为:
file://localhost/absolute/path/to/file [ok]

或者您可以省略主机名(但不能省略斜杠):
file:///absolute/path/to/file [ok]

但不包括这个:
file://file_at_current_dir [no way]

也不是这个:

file://./file_at_current_dir [no way]

我刚刚确认了通过Python的urllib2.urlopen()方法

更多细节请参考http://en.wikipedia.org/wiki/File_URI_scheme

"file:///foo.txt" is okay, while "file://foo.txt" is not,
although some interpreters manage to handle the latter

11
请问如何使用相对文件语法中的“.”创建URI? - cogmission
4
你不明白我回答中的第四个例子吗?它清楚地提到在URI中无法使用“.”。虽然你可以这样做,但没有任何意义,也无法实现你可能期望的效果。你还可以参考本页中排名第二高的回答(https://dev59.com/WWsz5IYBdhLWcg3wfn-6#19204256)。尽管它需要更长的阅读和理解时间。 - RayLuo
1
RFC3986的§4.2节指出相对引用是可以接受的。在给定上下文("基础URI")内,使用规范解析引用的过程。第一个"no way"是忽略URI的结构,并且绝不涉及路径。第二个是在文件系统根目录中名为file_at_current_dir的文件。我在此示例中使用Python来强调“在构建字符串时没有当前目录”的事实。 - amcgregor
实际上,从Python加载requirements.txt绝望地需要一个相对URL。如果您不知道程序加载的位置,并且在多台机器和存储库上硬编码目录位置是奇怪的话,“老派本地路径”将无法工作。 - J. Gwinner
我在我的 requirements.txt 文件中有一个指向本地文件的路径 /${HOME}/mypackage.whl,但它被翻译成了 file://home/myuser/mypackage.whl,这是错误的。我该如何将其修正为 file:/// 呢? - Muhammad Faizan-Ul-Haq
显示剩余2条评论

27

如果路径中包含'.'或'..',且没有根路径作为前缀,那么就无法使用完整的文件URI。无论你使用'file://./.bashrc'还是'file:///./.bashrc'这些路径都是没有意义的。如果你想使用相对链接,请不要使用协议/权限部分:

<a href="./.bashrc">link</a>

如果您想使用完整的URI,必须指定相对路径的根目录:

<a href="file:///home/kindrik/./.bashrc">link</a>

根据RFC 3986规定

The path segments "." and "..", also known as dot-segments, are
defined for relative reference within the path name hierarchy.  They
are intended for use at the beginning of a relative-path reference
(Section 4.2) to indicate relative position within the hierarchical
tree of names.  This is similar to their role within some operating
systems' file directory structures to indicate the current directory
and parent directory, respectively.  However, unlike in a file
system, these dot-segments are only interpreted within the URI path
hierarchy and are removed as part of the resolution process (Section
5.2).

The complete path segments "." and ".." are intended only for use
within relative references (Section 4.1) and are removed as part of
the reference resolution process (Section 5.2).  However, some
deployed implementations incorrectly assume that reference resolution
is not necessary when the reference is already a URI and thus fail to
remove dot-segments when they occur in non-relative paths.  URI
normalizers should remove dot-segments by applying the
remove_dot_segments algorithm to the path, as described in Section 5.2.4.

The complete path segments "." and ".." are intended only for use
within relative references (Section 4.1) and are removed as part of
the reference resolution process (Section 5.2) 

RFC 3986 描述了如何从 URI 中移除这些 "." 和 ".." 的算法。


24
在终端中,您可以使用 “$PWD” 引用当前目录,并输入“file://$PWD/.bashrc” 来访问特定的 ".bashrc" 文件。

这对于相对路径也可以正常工作,“file://$PWD/../parentchilddir/somefile.txt”。 - nilsmagnus
2
正如@kai-dj在不同的回答中提到的那样,如果$PWD包含了像C:/Users/Joshua Pinter/这样的空格,那么路径将无效。需要以某种方式进行转义。 - Joshua Pinter
你可以使用变量字符串替换,用空格来转义空格,例如 file://${PWD// /\\ }/relative/path - Steve Goossens
1
小提示,反斜杠转义不是正确的形式。这是一个URI。使用百分号编码,并注意空格字符本身可以优化为+。此外还要注意,URI允许UTF-8,因此许多Unicode字符(如重音字母、表情符号、§等符号)实际上根本不需要编码。另外需要注意的是:未编码的URI将被用户代理自动编码,因此作为字符串(包含空格)使用可能是可以的。(空格会导致shell扩展/进程参数列表构建问题。) - amcgregor

21

file:后面不应该加上双斜杠,正确的形式是

'file:.bashrc'

参见RFC 3986path-rootless的定义


9
请参考同一 RFC 中 Syntax Components, §3 的定义,以及描述其相对构成(包括 //)的§3.2 Authority部分。然后注意到该RFC中定义的 file: 方案的第 2 节(https://tools.ietf.org/html/rfc8089#section-2),该节仅允许 path-absolute。即使某些系统通过约定允许它们,但相对 file: URI 在技术上并不存在。 - amcgregor
1
当尝试消除这个超级烦人的错误:“无效的JSON-LD语法; @context @id值必须是绝对IRI、空白节点标识符或关键字。”时,这使得PyLD JSON-LD解析引擎感到高兴。我只想要一个相对ID,让我自己来! - DeusXMachina
我在requirements.txt文件中尝试了这个,但返回的错误是ERROR: Invalid requirement: 'apsw @ file:.installPreqs/apsw-3.37.0-cp39-cp39-win_amd64.whl' (from line 2 of requirements.txt)。使用file:./install也不起作用。 - J. Gwinner

6

我不知道您的使用情况。

在我的Node.js代码中,我有类似的需求,因此当我需要一个相对于工作目录的文件url时,我会按照以下方式创建url...

const url = "file://" + process.cwd() + "/" + ".bashrc";

5

URI始终是绝对的(除非它们是相对URI,这是一种不带模式的不同实体)。这是因为URI是一种服务器-客户端技术,引用服务器的工作目录就没有意义了。反过来,引用文件系统在服务器-客户端上下文中也没有意义。尽管如此,《RFC 8089》仅允许使用绝对路径:

路径组件表示文件系统中文件的绝对路径。

但是,如果我要假设一种非标准扩展,则会选择以下语法:

file:file.txt
file:./file.txt

RFC 8089规定了非本地路径file://<主机的完全限定域名>/路径和本地路径file:/路径file://localhost/路径file:///路径。由于我们几乎肯定是在尝试指定一个本地相对路径(即可由"局部文件系统API"访问),且因.既不是FQDN也不是hostname,所以最简单的file:方案+方案特定部分URI语法最有意义。

太棒了,file:./file.txt 作为相对路径的修复方法适用于通用 URL! - Mohammad Kanan

2
在Unix shell脚本中,我成功实现了以下内容:
file://`pwd`/relative-path

在您的特定情况下:
file://`pwd`/.bashrc

在VIM中呢? - 71GA
@71GA,不好意思,我不太熟悉vim,无法回答你的问题。 - 1234ru

1

有一个解决方法可能会有所帮助。

如果在开发时您只能指定文件的相对路径,但需要一个URL(需要知道绝对路径),请使用以下代码:

new File("relative/path/to/file").toURI().toURL();

这样,您将获得一个指向相对路径中文件的URL。


这个不起作用...它会生成一个包含".. "的错误的URL。 - undefined
它包括了“..”,但并没有损坏。如果你担心“..”,可以使用.getCanonicalPath()方法。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接