12

I have a script which requires an directory as one argument. I want to support the two form: one is like

a/b/c

(no slash at the end) and another is like

 a/b/c/

(has slash at the end).

My question: given either of the two form, how can I just keep the first form unchanged and strip the last slash of the second form to convert it to the first form.

  • 2
    Not that it should be much of a problem - a double slash anywhere except at the start is equivalent to a single slash, so don't worry about joining them using /. – muru Apr 23 '15 at 1:40
  • @muru I did not know this before :). – Yulong Ao Apr 23 '15 at 1:46
  • Here is a good Q/A on Multiple Consecutive Path Separators – Peter.O Apr 23 '15 at 8:42
  • 1
    @muru A slash at the end can make a difference, such as the difference between acting on a symlink and acting on the directory it points to, or the source argument of rsync. – Gilles Apr 24 '15 at 4:55
  • @Gilles indeed, but as you can see, I'm talking of joining paths. – muru Apr 24 '15 at 4:56
16
dir=${1%/}

will take the script's first parameter and remove a trailing slash if there is one.

6

To remove a trailing slash if there is one, you can use the suffix removal parameter expansion construct present in all POSIX-style shells:

x=${x%/}

There are a few complications. This only removes a single slash, so if you started with a/b/c// then you'll still end up with a slash. Furthermore, if the original path was /, you need to keep the slash. Here's a more complex solution that takes care of these cases:

case $x in
  *[!/]*/) x=${x%"${x##*[!/]}"};;
  *[/]) x="/";;
esac

Alternatively, in ksh, or in bash after shopt -s extglob:

[[ x = *[!/] ]] || x=${x%%*(/)}

Note that in many cases, it doesn't matter that there is a trailing slash. It does matter if the argument is a symbolic link to a directory: with a trailing slash, the argument designates the directory, whereas with no trailing slash, the argument designates the symbolic link itself. It also matters with a few other programs, for example the source argument of rsync is treated differently depending on the presence of a trailing slash.

1

realpath resolves given path. Among other things it also removes trailing slashes. Use -s to prevent following simlinks

DIR=/tmp/a///
echo $(realpath -s $DIR)
# output: /tmp/a

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.