1. Overview

In this tutorial, we’ll check some ways to build a complete Linux path by concatenating two strings holding the subpaths.

First, we’ll check some basic techniques to accomplish this. Then, we’ll discuss a generic solution that allows handling some of the special cases appearing when concatenating paths.

2. Concatenating Strings to Build a Path

Let’s begin by checking a use case where we need to concatenate strings to get a complete path:

$ my_home_dir="/home/shubh/baeldung/"

Here, let’s consider that the path defined by the variable my_home_dir is our current working directory. Let’s also clone a git repository in the my_home_dir path:

$ repo_path="tutorials/linux-bash/command-line-arguments/src/main/bash"

The variable repo_path holds the path of the file users-loop.sh within the repository. Hence, to get the absolute path of this file, we need to concatenate my_home_dir  and repo_path variables.

Let’s examine a possible solution:

$ file_path="$my_home_dir/$repo_path"
$ echo $file_path
/home/shubh/baeldung//tutorials/linux-bash/command-line-arguments/src/main/bash

Here,  as we can see, the variable file_path holds the complete path of the file users-loop.sh. We’ll now verify this by listing (ls) the file users-loop. sh using this variable:

$ ls -lrt $file_path/users-loop.sh
-rw-r--r-- 1 shubh shubh 86 May  3 18:07 /home/shubh/baeldung//tutorials/linux-bash/command-line-arguments/src/main/bash/users-loop.sh

As we can see, our solution works as expected. However, observe the two continuous slashes (.. baeldung//tutorials ..) in the path, though. Notably, as per the POSIX standards for pathname resolution, consecutive path separators (i.e., / ) are equivalent to a single path separator. Let’s run an example to verify this:

$ echo $my_home_dir
/home/shubh/baeldung/
$ repo_base_dir="${my_home_dir}///tutorials" && echo $repo_base_dir
/home/shubh/baeldung////tutorials
$ ls -ld  $repo_base_dir/linux-bash
drwxr-xr-x 1 shubh shubh 512 May  3 18:07 /home/shubh/baeldung////tutorials/linux-bash

It works! Multiple / is not an issue in Linux pathnames. However, for better readability, one might want to get rid of the extra slash characters in the path. We can use the realpath command to achieve this:

$ ls -ld $(realpath ${repo_base_dir})/linux-bash
drwxr-xr-x 1 shubh shubh 512 May  3 18:07 /home/shubh/baeldung/tutorials/linux-bash

Here we get the absolute pathname, which is free of extra / references. Note, we’re using command substitution here to execute the realpath command while listing the directory information.

3. A Generic Solution That Handles Special Cases

In the previous section, we used the technique to concatenate strings containing Linux paths. But, there can be some special cases, which we’ll discuss in this section.

What happens if someone issues a first argument that is a blank string or can use a relative path to concatenate with the first path string?

Let’s check a solution that handles the special cases stated above:

concatenate_paths() {
   base_path=${1}
   sub_path=${2}
   full_path="${base_path:+$base_path/}$sub_path"
   full_path=$(realpath ${full_path})
   echo $full_path
}

Here, we have created a Bash function concatenate_paths that accepts the two input strings to be concatenated as arguments.

In this function, the first argument gets stored in the base_path variable and the second argument in the sub_path variable. Then, we’re using shell parameter expansion to handle the cases of empty base_path:

${base_path:+$base_path/}

In the above condition, if base_path is null or unset, nothing is substituted. Else, the base_path is substituted with “base_path/”. Hence, we add the file separator to the base_path only if the base_path is defined. Later, we are using the realpath command to deal with the multiple slash (/) situations. Additionally, the realpath command also allows us to use the relative paths while concatenating the strings.

Let’s verify our code with some examples:

$ concatenate_paths "/home/shubh//" "baeldung//linux/"
/home/shubh/baeldung/linux

$ concatenate_paths "/home/shubh//baeldung/linux" "foo.bar"
/home/shubh/baeldung/linux/foo.bar

The results are in line with our expectations. Let’s now test by giving the first argument as blank:

$ concatenate_paths "" "/home/shubh//baeldung/linux/foo.bar"
/home/shubh/baeldung/linux/foo.bar

$ ls -lrt $(concatenate_paths "/home/shubh//baeldung/linux" "foo.bar")
-rw-r--r-- 1 shubh shubh 0 May  3 21:02 /home/shubh/baeldung/linux/foo.bar

It produced the correct path, and we also verified this by listing the file. Now, lets’ run a test case by giving relative paths:

$ ls -lrt $(concatenate_paths "/home/shubh//baeldung/" "./linux/foo.bar")
-rw-r--r-- 1 shubh shubh 0 May  3 21:02 /home/shubh/baeldung/linux/foo.bar

Here we are proving the relative path (using the dot operator) wrt. to the first input, and the output looks good. Let’s make our test case a bit more complex and verify:

$ ls -lrt $(concatenate_paths "/home/shubh//baeldung/linux" "../linux/foo.bar")
-rw-r--r-- 1 shubh shubh 0 May  3 21:02 /home/shubh/baeldung/linux/foo.bar

It works seamlessly! Hence, we’re able to verify all the special cases discussed above.

4. Conclusion

In this tutorial, we checked ways to concatenate two strings to build a complete path in Linux.

First, we checked a use case of the problem statement. Then, we learned some basic techniques that can be used to handle our use case.

Later, we discussed some of the special cases that might arise while building a complete path.

Lastly, we checked the ways to handle the special cases by writing a generic solution to the problem statement.

As always, the examples used in this article are available on GitHub.