1

I'm looking for a Bash equivalent of Python's os.path.join. I'm trying to prompt the user for a directory path, which then will be used (with the help of path join equivalent) to do other stuff.

pam
  • 1,175
  • 5
  • 15
  • 28
  • You can always just use `${dirpath}/${filename}`. Python has `os.path.join` because `/` isn't portable, it only works on Unix-like pathnames. But `bash` only works with Unix-based pathnames. (Even if you build a MinGW/native `bash` for Windows.) – abarnert Apr 17 '15 at 05:53
  • I want to do it through a shell script. cd path didn't work for me. @abarnert I tried echo to get the path, but that again I'm totally skeptical about. – pam Apr 17 '15 at 05:55
  • I don't understand the question(s) in that last comment. If your shell script has variables named `dirpath` and `filename`, then `${dirpath}/${filename}` joins them together, just like `os.path.join(dirpath, filename)` would in Python. – abarnert Apr 17 '15 at 05:58
  • `"$dirpath/$filename"` is perfectly valid. Don't forget to double-quote the string in case there are embedded spaces. You don't need `{ }` around the variables because `/` terminates the variable name. – cdarke Apr 17 '15 at 06:19
  • 1
    @cdarke: I don't like to leave the braces off in code for novices who don't know the rules for identifiers and don't seem likely to ask until they have a bug 3 months from now… – abarnert Apr 17 '15 at 06:50

2 Answers2

2

It's perfectly safe to use, e.g., "${dirpath}/${filename}" in a bash script.

bash only understands POSIX-style pathnames. Even if you build a MinGW/native bash on Windows. That means / is always the path separator. And it means that it never hurts to put two slashes in a row, so even if $dirpath happens to end in '/', everything is fine.

So, for example:

$ cat join.sh
#!/bin/bash
echo -n 'Path: '
read dirpath
echo -n 'Filename: '
read filename
ls -l "${dirpath}/${filename}"
$ ./join.sh
Path: /etc/
Filename: hosts
-rw-r--r--  1 root  wheel  236 Sep 15  2014 /etc/hosts

In Python, it's not safe to just use / this way. Python handles native-format pathnames on POSIX and POSIX-like systems, but also handles native-format pathnames on Windows.*, in which the path separator is \, two backslashes have a special meaning in certain places, you have drive letters to worry about, etc. So, you have to use os.path.join to be portable.

* It also has code for classic Mac (which uses colons), VMS (which uses a mix of different things that you don't want to know about), etc., if you're using an old enough Python.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • @cdarke: Yes, Windows NT does accept `/` paths. Except that they're not guaranteed to work in a `\\.\` "long Unicode" path, may not be sent properly over CIFS networks in an SMB path, may be confused with flags by some command-line tools (including the ones that come with Windows itself), etc. – abarnert Apr 17 '15 at 06:13
  • @cdarke: What about it in particular? That's a long article. (Also, why link to a link to the article instead of to the article itself?) – abarnert Apr 17 '15 at 06:49
  • For specific uses of the result it is save to join two path parts using a slash. It is not save e. g. if you string-compare this result with a given path, e. g. `if [ "${part1}/${part2}" = "$(pwd)" ]`. The Python `os.path.join()` is superior in this aspect; it removes additional slashes. – Alfe Sep 29 '16 at 15:00
1

You might be looking for the readlink command. You can use readlink -m "some/path" to convert a path to the canonical path format. It's not quite path.join but it does provide similar functionality.

Edit: As someone pointed out to me readlink is actually more like os.path.realpath. It is also a GNU extension and not available on all *nix systems. I will leave my answer here in case it still helps in some way.

Phillip
  • 79
  • 6
  • 1
    That's not similar to `os.path.join`. It _is_ similar to `os.path.realpath`, but that's a completely different thing from `os.path.join`. Also, `readlink -m` is a GNU extension that isn't on other *nix systems. (The OP did tag this "linux", but also "unix"; I'm not sure if that means he wants a portable solution or not…) – abarnert Apr 17 '15 at 05:59
  • ⁺¹ for mentioning the (ab)use of `readlink -m` to canonize a path. Didn't know that one yet :) – Alfe Sep 29 '16 at 15:06