# Appending trailing slashes to paths

**URL:** <https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922>\
**Category:** Internals & Design\
**Created:** [October 5, 2018, 11:50am UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922 "2018-10-05T11:50:09Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![fbruetting](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fbruetting/32/4463_2.png) [@fbruetting](https://discourse.julialang.org/u/fbruetting)\
**Post date:** [October 5, 2018, 11:50am UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/1 "2018-10-05T11:50:09Z")

</div>

Won’t it be useful to always append trailing slashes to paths for all core path functions? We then would see at first glance if a path leads to a directory or a file. When you see for example `~/config`, you can’t tell if this is a file or a directory – the implementation of this convention would clarify this.

Some additional thoughts:

- Currently we have both, as `normpath(@ __FILE__ , "..")` shows a trailing slash, whereas `normpath(@__DIR)` (or just `@__DIR__`) show no trailing slash. This could be unified.

- `dir * "/" * file` would then expand to `"<DIR>//<FILE>"`. That doubled slash makes no difference, which makes this backwards-compatible.

- It should be better for Windows compatibility, as I assume `dir * "/" * file` wouldn’t work there, whereas `dir * file` (with trailing slash convention) should do the trick, as this should automatically use a backslash.

- `dir * "/" * "var"` could expand to `/var` if `dir` is empty – which could have negative impact on system roots.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [October 5, 2018, 12:03pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/2 "2018-10-05T12:03:01Z")

</div>

You should use `joinpath` though.

---

<div class="post-metadata">

**Author:** ![fbruetting](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fbruetting/32/4463_2.png) [@fbruetting](https://discourse.julialang.org/u/fbruetting)\
**Post date:** [October 5, 2018, 12:07pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/3 "2018-10-05T12:07:22Z")

</div>

“You should do it right” solves every problem on earth, hooray!

I know about `joinpath()`, still a LOT of people (especially beginners) use `… * "/" * …`. Everything can be further polished, and I think that this would make things clearer and improves some situation for beginners without introducing negative consequneces. If you are against, then please describe at least a downside argument.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [October 5, 2018, 12:26pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/4 "2018-10-05T12:26:33Z")

</div>

> [@fbruetting](#):
>
> still a LOT of people (especially beginners) use `… * "/" * …` .

I don’t know if this is true, but if anyone is handling paths like this, then they shouldn’t. This means that your last 3 examples are not very relevant.

> [@fbruetting](#):
>
> would see at first glance if a path leads to a directory or a file

Paths have existence independently of the file system. You cannot tell if `"/some/path"` is a file, directory, or neither, until you examine it (eg `isdir`), except for some cases (`isdirpath`).

---

<div class="post-metadata">

**Author:** ![fbruetting](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fbruetting/32/4463_2.png) [@fbruetting](https://discourse.julialang.org/u/fbruetting)\
**Post date:** [October 5, 2018, 1:24pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/5 "2018-10-05T13:24:32Z")

</div>

> [@Tamas\_Papp](#):
>
> I don’t know if this is true, but if anyone is handling paths like this, then they shouldn’t. This means that your last 3 examples are not very relevant.

They should also not do memory bugs in C and null pointer exceptions in Java…

An example – I just stumbled upon this thread here:

> <https://stackoverflow.com/questions/35466572/absolute-path-of-the-project-root-directory-in-julia>

I know this is not necessary, but it would make Julia more nice, see this screen shot of my Juno session:

![Bildschirmfoto%20von%202018-10-05%2015-22-02](https://global.discourse-cdn.com/julialang/original/3X/a/7/a7d30803aeb7d2cf2da966c93a866d02559a942f.png)

Is it a folder or a file? With `normpath()` adding a trailing slash, you would be able to infer that! Yeah, `isfile()` is 100% precise, but here a trailing slash just makes it more comfortable and you get maybe 90% precision instead of currently none at all. And again, I don’t see a reason not to do that.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [October 5, 2018, 2:20pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/6 "2018-10-05T14:20:48Z")

</div>

> [@Tamas\_Papp](#):
>
> I don’t know if this is true, but if anyone is handling paths like this, then they shouldn’t.

Why not? Windows accepts forward slashes as path separators (except for command-line tools), even if backslashes are more idiomatic.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [October 5, 2018, 2:32pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/7 "2018-10-05T14:32:49Z")

</div>

My specific point was this: if you use string concatenation instead of `joinpath`, it may work, but it can also miss some [corner cases](https://github.com/JuliaLang/julia/blob/50c27fd96062b19a3b0fef8b423a5e932568927c/base/path.jl#L258-L267).

---

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [October 5, 2018, 2:55pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/8 "2018-10-05T14:55:17Z")

</div>

For what it’s worth, neither Python, Ruby nor bash append the trailing `/`. (Well, for bash it of course depends a bit on the context, but for example `pwd` doesn’t append.) If I had to take a guess I’d say it’s probably very standard not to append it.

I’m not necessarily arguing Julia should follow precedents set by those languages (in many cases it does not for good reason and the result is wonderful), but I don’t personally see any compelling reason to buck the trend here, particularly when Julia has a pretty extensive set of file management functionality in `Base`.

If anything, it might be worth investigating why `normpath(dir,"..")` appends trailing slash, as that would seem to be the non-standard thing here. Even weirder is that it only seems to do that when you use `".."`. It doesn’t seem like a big deal, but it’s always nice to have predictable behavior.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [October 5, 2018, 3:12pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/9 "2018-10-05T15:12:48Z")

</div>

> [@ExpandingMan](#):
>
> If I had to take a guess I’d say it’s probably very standard not to append it.

For `bash`, it would definitely be very bad practice to append a `/` automatically, since many command line tools (eg `cp` and `rsync`) do something completely different depending on whether you append one.

FWIW, I think that conditioning on a trailing `/` is an unfortunate design choice (and consequently a source of many bugs), but it looks like it is established practice, so I am not sure Julia would benefit from automatically appending a `/` either — it would make `run(`something $(withpath)`)` tricky.

---

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [October 5, 2018, 3:26pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/10 "2018-10-05T15:26:42Z")

</div>

I guess it might have been nice if `dir/` were standard notation for a directory to denote that fact that it’s a directory. We’re 40 years too late on that decision though 😆

---

<div class="post-metadata">

**Author:** ![fbruetting](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fbruetting/32/4463_2.png) [@fbruetting](https://discourse.julialang.org/u/fbruetting)\
**Post date:** [October 5, 2018, 3:27pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/11 "2018-10-05T15:27:24Z")

</div>

> [@Tamas\_Papp](#):
>
> For `bash` , it would definitely be very bad practice to append a `/` automatically, since many command line tools (eg `cp` and `rsync` ) do something completely different depending on whether you append one.

Wouldn’t `mv <file> <dir>` in a shell actually be better and safer when `dir` contains a trailing slash? This way you cannot as easily accidentally mix files with folders in commands, so that should be more precise and a bit like type-safety…? When you want to move something in a directory and use a path without a trailing slash, `mv` would think that this is a file instead, or? (Sorry, I’m not really into shell scripting…)

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 5, 2018, 4:52pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/12 "2018-10-05T16:52:59Z")

</div>

> [@ExpandingMan](#):
>
> If anything, it might be worth investigating why `normpath(dir,"..")` appends trailing slash, as that would seem to be the non-standard thing here. Even weirder is that it only seems to do that when you use `".."` . It doesn’t seem like a big deal, but it’s always nice to have predictable behavior.

May be a bug. I tried to emulate Python behavior closely here, but `normpath` is pretty tricky to implement.

---

<div class="post-metadata">

**Author:** ![Juser](https://avatars.discourse-cdn.com/v4/letter/j/34f0e0/32.png) [@Juser](https://discourse.julialang.org/u/Juser)\
**Post date:** [October 5, 2018, 6:59pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/13 "2018-10-05T18:59:40Z")

</div>

> [@fbruetting](#):
>
> a LOT of people (especially beginners) use `… * "/" * …` .

Guilty as charged… Did not know I was doing this wrong and should have been using `joinpath`. You learn something new every day…

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [October 6, 2018, 2:42pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/14 "2018-10-06T14:42:52Z")

</div>

Does anybody think a `Path` or `File` or `Dir` type would be useful?

I’ve had quite a few instances where I wanted methods in the line of:  
`load_data(file_name::String)`  
`load_data(data::String)`

When dealing with these I had to come up with artificial solutions when what I really would’ve wanted was to dispatch on a `Path` type (or `File` or `Dir`):  
`load_data(file_name::File)`

This would also address the “is it a file or a dir” question and would have distinct `show`, `print` etc functions which could take into account end slashes, extensions, etc.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [October 6, 2018, 6:02pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/15 "2018-10-06T18:02:53Z")

</div>

There is [GitHub - rofinn/FilePaths.jl: A type based approach to working with filesystem paths in julia](https://github.com/rofinn/FilePaths.jl), and it also has been discussed on github to include this kinda thing in base (but I cannot find it).

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 6, 2018, 7:26pm UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/16 "2018-10-06T19:26:30Z")

</div>

There was also a work-in-progress Julep for this idea: [https://github.com/JuliaLang/Juleps/pull/26](https://github.com/JuliaLang/Juleps/pull/26). Didn’t get far enough to make it into Julia 1.0 but still an interesting idea that would be worthy of someone exploring fully to see how nice one can make working with paths with this approach.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [October 7, 2018, 5:44am UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/17 "2018-10-07T05:44:23Z")

</div>

> [@fbruetting](#):
>
> Wouldn’t `mv <file> <dir>` in a shell actually be better and safer when `dir` contains a trailing slash?

I am not saying that the interface to `mv` etc is well-designed (quite the opposite), but at this point some tools acting differently depending on the trailing `/` is pretty much a given for Julia.

---

<div class="post-metadata">

**Author:** ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)\
**Post date:** [October 7, 2018, 7:16am UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/18 "2018-10-07T07:16:14Z")

</div>

> [@ExpandingMan](#):
>
> Even weirder is that it only seems to do that when you use `".."`

It depends on `isdirpath`:

```julia
julia> path = "/tmp/testdir/";isdirpath(path),normpath(path)
(true, "/tmp/testdir/")

julia> path = "/tmp/testdir/.";isdirpath(path),normpath(path)
(true, "/tmp/testdir/")

julia> path = "/tmp/testdir/..";isdirpath(path),normpath(path)
(true, "/tmp/")

julia> path = "/tmp/testdir";isdirpath(path),normpath(path)
(false, "/tmp/testdir")

```

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [October 8, 2018, 12:19am UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/19 "2018-10-08T00:19:48Z")

</div>

> [@StefanKarpinski](#):
>
> emulate Python

@StefanKarpinski Probably not relevant here, but do you look at `os.path` or `pathlib`? I’ve heard that `os.path` has some issues that cannot be fixed due to backward compatibility guarantee. It looks like `pathlib` got those things right. [PEP 428 – The pathlib module – object-oriented filesystem paths | peps.python.org](https://www.python.org/dev/peps/pep-0428/#sane-behaviour)

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 8, 2018, 12:46am UTC](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922/20 "2018-10-08T00:46:12Z")

</div>

Nope. Mostly looks like it requires a special path type, which we could still do.

[Next page](https://discourse.julialang.org/t/appending-trailing-slashes-to-paths/15922.md?page=2)
