Say for example I have a path like
path_1=/this/is/a/path/with/slash/
How do I get the following:
/this/is/a/path/with/slash
so the path without the last "/"
All POSIX shells have (c.f. man bash
) "Parameter Expansion: Remove matching suffix pattern". So, use
$ echo "${path_1%/}"
/this/is/a/path/with/slash
If the variable's value does not end in a slash, then the value would be outputted without modification.
/
because it'll turn into the empty string, which means something entirely different.
Commented
Jan 31, 2022 at 16:41
You can use realpath
DIR=/tmp/foo///
echo "$(realpath -s "$DIR")"
# output: /tmp/foo
Another way of removing the slash is
$ echo "$(dirname -- "$path")/$(basename -- "$path")"
We just combined the two common shell commands dirname
and basename
.
$path
and also the command substitution itself to avoid the issues mentioned in When is double-quoting necessary?. (See also What's the right way to quote $(command $arg)?). Also if the filename can start with a dash, --
is needed so that it's not taken as a bunch of options. Of course this will also rewrite paths like foo/
into ./foo
.
path
as the variable's name. In the bash
shell, it doesn't matter, but the path
array variable in the zsh
shell is tied to the PATH
variable and will contain the elements of the PATH
variable's :
-delimited values.
You can use sed in a simple way like this:
$ echo $path_1|sed 's-/$--'
/this/is/a/path/with/slash
Explanation:
-
the most common is /
, but since we are looking for the / itself, it is easier to use some other character. If one really wants to use /, then it would need to be escaped like so:$ echo $path_1|sed 's/\/$//'
There are several options. I usually canonicalise the path. When you canonicalise a path, you get the base path.
For example, if the path is a link to a folder, the canonical form will get the actual path. It will also remove all double-slashes, which although unusual, are allowed in Unix and Linux.
Suppose ~/lf
is a link to ~/.hidden/food/limes/
.
PATHNAME=~/lf//price/
CANONICAL_PATH="$( realpath --canonicalize-existing "${PATHNAME}" )"
echo "${CANONICAL_PATH}"
The result would be /home/kamil/.hidden/food/limes/price
This also works for files, block devices, etc., although of course they don't have a trailing slash. For example, on my system:
PATHNAME=/dev/disk/by-partlabel/Boot
CANONICAL_PATH="$( realpath --canonicalize-existing "${PATHNAME}" )"
echo "${CANONICAL_PATH}"
The result is /dev/nvme0n1p2
If you aren't sure that the path exists, you need to add some error-checking.
PATHNAME=~/lf//price/
CANONICAL_PATH="$( realpath --canonicalize-existing "${PATHNAME}" 2>/dev/null )"
if [[ -z ${CANONICAL_PATH} ]]
then
echo "Path doesn't exist: ${PATHNAME}" >&2
else
echo "Canonical path is ${CANONICAL_PATH}"
fi
…/slash/
leads to a directory), if you want to postpend acomponent
and you're not sure if$path_1
ends with/
, don't bother and just postpend/component
:…/slash//component
will work like…/slash/component
. There's at least one situation when the trailing slash matters though: ifslash
is a symlink to a directory then…/slash/
means the directory, certainly not the symlink, while…/slash
may mean the symlink. Then your question is useful.