105

Assume that the scheme for a uri is "file". Also assume that the path starts with '.'

An example path is './.bashrc'. How would the fulluri look? 'file://./.bashrc' appears odd to me.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
user592419
  • 5,103
  • 9
  • 42
  • 67
  • 3
    According to Wikipedia http://en.wikipedia.org/wiki/Uniform_resource_identifier apparently you can just omit the scheme and have "./.bashrc" as the uri when you are referring relatively. However, this is just a guess and I'm not sure if it is actually how it works. – Tony Dec 17 '11 at 20:28
  • 2
    @Tony - Thanks, that works fine for making relative references in .docx files - just unzip, find the "file:///long-absolute-path/relative-path" references, and replace with "relative-path" – tucuxi Nov 30 '12 at 12:07
  • 1
    Strictly omitting the prefix does not always work, as URIs can have special characters encoded with percent signs (e.g. `%20` = space); depending on the application you will likely need to replace the escaped characters with their actual representation. – sleblanc May 30 '16 at 20:03
  • Chromium will soon lose `file://` support. https://bugs.chromium.org/p/chromium/issues/detail?id=1299624 – 9pfs Feb 21 '22 at 23:11

8 Answers8

100

In short, a file URL takes the form of:

file://localhost/absolute/path/to/file [ok]

or you can omit the host (but not the slash):

file:///absolute/path/to/file [ok]

but not this:

file://file_at_current_dir [no way]

nor this:

file://./file_at_current_dir [no way]

I just confirmed that via Python's urllib2.urlopen()

More detail from 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
RayLuo
  • 17,257
  • 6
  • 88
  • 73
  • Is it not also possible to use file:/absolute/path or file:relative (even though this won't work) as you could remove authority for file protocol. – Cem Kalyoncu Jun 05 '16 at 09:58
  • 10
    @RayLuo Still doesn't answer question of how to create a URI using relative file syntax of "." ? – cogmission Sep 12 '18 at 16:59
  • 3
    @cogmission Don't you get the 4th example in my answer? It clearly mentioned there is no way to use "." in URI. Well, you could, it just doesn't make any sense, and won't achieve what you might expect otherwise. You can also refer to the [2nd-highest upvoted answer right in this page](https://stackoverflow.com/a/19204256). It is longer for you to read and figure out, though. – RayLuo Sep 12 '18 at 20:53
  • 1
    [§4.2 of RFC3986](https://pretty-rfc.herokuapp.com/RFC3986#relative-ref) says relative references are fine. [Canonical process for _resolving_ the reference](https://pretty-rfc.herokuapp.com/RFC3986#reference-resolution) within a given context ("base URI"). The first "no way" is ignoring the structure of a URI, and is in no way referring to the path. The second is a file named `file_at_current_dir` at the root of the filesystem. I [use Python in this example](http://s.webcore.io/152f71/uri.png) to really highlight the fact that there **is no current directory** when **building strings**. – amcgregor Sep 25 '19 at 14:52
  • @amcgregor As you quoted, the relative reference in RFC3986 works only within a given context i.e. the "base URI". That condition can be satisfied if it is inside an web page, which uses `http://` or `https://` scheme. But in a `file://` scheme that the OP asks, it semantically depends on where the calling program's CWD is, even if that calling program manages to interpret that URI. In practice, where will you use that `file://` uri anyway? If it is a CLI tool, you can completely avoid `file://` and just fall back to old school local path. If it is in a browser, we can't assume its CWD either. – RayLuo Sep 25 '19 at 20:08
  • Actually, loading requirements.txt from Python desperately needs a relative URL. "Old school local path" won't work if you don't know where the program is loaded, and hard coding directory locations on multiple machines and repo's is weird. – J. Gwinner Apr 19 '22 at 03:53
  • I have a path to a local file in my requirements.txt as /${HOME}/mypackage.whl and it get translated to file://home/myuser/mypackage.whl which is wrong, how can i fix it to file:/// instead ? – Muhammad Faizan-Ul-Haq Sep 21 '22 at 07:12
27

It's impossible to use full file: URI with '.' or '..' segments in path without root part of that path. Whether you use 'file://./.bashrc' or 'file:///./.bashrc' these paths will have no sense. If you want to use a relative link, use it without protocol/authority part:

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

If you want to use full URI, you must tell a root relative to which your relative path is:

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

According to 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 describes even an algorithm of removing these "." and ".." from URI.

Community
  • 1
  • 1
kinORnirvana
  • 1,667
  • 2
  • 17
  • 22
24

In a terminal you could type "file://$PWD/.bashrc" using "$PWD" to refer to the current directory.

andz
  • 339
  • 3
  • 4
  • This works fine for relative paths as well, "file://$PWD/../parentchilddir/somefile.txt" – nilsmagnus Aug 02 '17 at 11:33
  • 2
    As @kai-dj mentioned in a different answer, if `$PWD` contains whitespaces like `C:/Users/Joshua Pinter/` then the path will not be valid. Needs to be escaped somehow. – Joshua Pinter May 20 '18 at 15:56
  • You could use variable string substitution, space for escaped space, e.g. `file://${PWD// /\\ }/relative/path` – Steve Goossens Nov 15 '18 at 18:16
  • 1
    Minor note, backslash escaping is not the correct form. This is a URI. [Use percent encoding](https://en.wikipedia.org/wiki/Percent-encoding) with the note that space characters themselves can be optimized down to a `+`. This has the additional note that URI permit UTF-8, so many Unicode characters (such as accented letters, emoji, symbols like §, etc.) actually require no encoding at all. Also of note: unencoded URI will be encoded automatically by user agents, so use as a string (containing spaces) may be a-OK. (Spaces are problems for shell expansion / process argument list building.) – amcgregor Sep 25 '19 at 14:28
21

You should not put double slash after file:. Correct form is

'file:.bashrc'

See RFC 3986, path-rootless definition

Community
  • 1
  • 1
Maxim Reznik
  • 1,216
  • 9
  • 12
  • 9
    Please refer to that same RFC, definition of [Syntax Components, §3](https://tools.ietf.org/html/rfc3986#section-3), and §3.2 Authority (describing its relative composition, which involves `//`), then make note of [§2 of the RFC defining the `file:` scheme](https://tools.ietf.org/html/rfc8089#section-2) which only permits `path-absolute`. Relative `file:` URI do not technically exist, even if certain systems allow them by convention. – amcgregor May 30 '19 at 13:08
  • 1
    This made the PyLD JSON-LD resolution engine happy when trying to silence this super annoying error: `Invalid JSON-LD syntax; @context @id value must be an absolute IRI, a blank node identifier, or a keyword.` . I just want a relative ID, let me do that! – DeusXMachina Aug 17 '20 at 19:39
  • I tried that in a requirements.txt file, and the error that comes back is that ERROR: Invalid requirement: 'apsw @ file:.installPreqs/apsw-3.37.0-cp39-cp39-win_amd64.whl' (from line 2 of requirements.txt). It doesn't work as file:./install ... either. – J. Gwinner Apr 19 '22 at 03:56
6

I don't know your use case.

I have a similar need in my node code, so when I need a file url relative to my working directory I create a url like so ...

const url = "file://" + process.cwd() + "/" + ".bashrc";
Ken Lin
  • 1,819
  • 21
  • 21
5

URIs are always absolute (unless they're relative URIs, which is a different beast without a schema). That comes from them being a server-client technology where referencing the server's working directory doesn't make sense. Then again, referencing the file system doesn't make sense in a server-client context either . Nevertheless, RFC 8089 permits only absolute paths:

The path component represents the absolute path to the file in the file system.

However, if I were to postulate a non-standard extension, I would choose the following syntax:

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

The explanation is that RFC 8089 specifies non-local paths file://<FQDN of host>/path and local paths file:/path, file://localhost/path, and file:///path. Since we're almost certainly trying to specify a local relative path (ie, accessible by "local file system APIs"), and because a . is not a FQDN or even a hostname, the simple file: scheme + scheme-sepecific-part URI syntax makes the most sense.

Aleksandr Dubinsky
  • 22,436
  • 15
  • 82
  • 99
2

In a unix shell script I managed to go with this:

file://`pwd`/relative-path

In your particular case:

file://`pwd`/.bashrc
1234ru
  • 692
  • 8
  • 16
0

There is a workaround that might help.

If at development time you can only specify a relative path to the file but need a URL (that requires to know the absolute path) use code like this:

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

With that you get a URL still pointing to the file in a relative path.

Queeg
  • 7,748
  • 1
  • 16
  • 42