Reputation: 25117
What is the simplest way to remove a trailing slash from each parameter in the '$@' array, so that rsync
copies the directories by name?
rsync -a --exclude='*~' "$@" "$dir"
The title has been changed for clarification. To understand the comments and answer about multiple trailing slashes see the edit history.
Upvotes: 169
Views: 149136
Reputation: 17850
Completely POSIX compliant
# recursively remove trailing slashes
remove_slashes() {
res="${1%/}"
if [ "$1" = "$res" ]
then echo "$res"
else remove_slashes "$res"
fi
}
# test:
remove_slashes a/b/
remove_slashes a/b////
remove_slashes ""
remove_slashes ///
remove_slashes ///a
Upvotes: 1
Reputation: 21956
The accepted answer will trim ONE trailing slash.
One way to trim multiple trailing slashes is like this:
VALUE=/looks/like/a/path///
TRIMMED=$(echo "$VALUE" | sed 's:/*$::')
echo "$VALUE" "$TRIMMED"
Which outputs:
/looks/like/a/path/// /looks/like/a/path
Upvotes: 65
Reputation: 2488
Approach I have used, when trimming directory arguments that are intended for rsync
, here using dirname
and basename
to split the path and then recombining the parts without the trailing slash.
raw_dir=/a/b/c/
trim_dir=$(dirname "$raw_dir")"/"$(basename "$raw_dir")
Upvotes: 1
Reputation: 2086
Taking note of a couple comments in the accepted answer:
//[...]
with a single slash /
(per @Dave comment)/
) (per @GordonDavisson comment)trimSlash() { for s; do sed -E 's://*:/:g; s:(^/)?/*$:\1:' <<< "${s}"; done; }
Not as concise as the answers using parameter substitution, but I think its worth the diligence.
Some test cases:
$ trimSlash "/" "///" "a/" "a/a/" "a///a/" "a/a" "a///a" "a///" "/a/a/" "///a///"
/
/
a
a/a
a/a
a/a
a/a
a
/a/a
/a
Upvotes: 0
Reputation: 1712
Not the most beautiful way, but quick and easy.
I just add a slash and remove all doubles. Assuming such a pattern will not be found elsewhere.
WORD="abc/"
WORD=$WORD'/'
WORD=`echo $WORD | sed s/'\/\/'/''/g`
echo $WORD
Upvotes: -1
Reputation: 7943
FYI, I added these two functions to my .bash_profile
based on the answers found on SO. As Chris Johnson said, all answers using ${x%/}
remove only one slash, these functions will do what they say, hope this is useful.
rem_trailing_slash() {
echo "$1" | sed 's/\/*$//g'
}
force_trailing_slash() {
echo "$(rem_trailing_slash "$1")/"
}
Upvotes: 11
Reputation: 16634
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
Upvotes: 40
Reputation: 401
This works for me: ${VAR%%+(/)}
As described here http://wiki.bash-hackers.org/syntax/pattern
May need to set the shell option extglob. I can't see it enabled for me but it still works
Upvotes: 40
Reputation: 52483
In zsh you can use the :a
modifier.
export DIRECTORY='/some//path/name//'
echo "${DIRECTORY:a}"
=> /some/path/name
This acts like realpath
but doesn't fail with missing files/directories as argument.
Upvotes: 6
Reputation: 120644
You can use the ${parameter%word}
expansion that is detailed here. Here is a simple test script that demonstrates the behavior:
#!/bin/bash
# Call this as:
# ./test.sh one/ two/ three/
#
# Output:
# one two three
echo ${@%/}
Upvotes: 267