Reputation: 3743
x=./gandalf.tar.gz
noext=${x%.*}
echo $noext
This prints ./gandalf.tar
, but I need just ./gandalf
.
I might have even files like ./gandalf.tar.a.b.c
which have many more extensions.
I just need the part before the first .
Upvotes: 1
Views: 123
Reputation: 196
Perhaps a regexp is the best way to go if your bash version supports it, as it doesn't fork new processes.
This regexp works with any prefix path and takes into account files with a dot as first char in the name (hidden files):
[[ "$x" =~ ^(.*/|)(.[^.]*).*$ ]] && \
noext="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
The first group captures everything up to the last /
included (regexp are greedy in bash), or nothing if there are no /
in the string.
Then the second group captures everything up to the first .
, excluded.
The rest of the string is not captured, as we want to get rid of it.
Finally, we concatenate the path and the stripped name.
It's not clear what you want to do with files beginning with a .
(hidden files). I modified the regexp to preserve that .
if present, as it seemed the most reasonable thing to do. E.g.
x="/foo/bar/.myinitfile.sh"
becomes /foo/bar/.myinitfile
.
Upvotes: 1
Reputation: 10123
Using extglob
shell option of bash
:
shopt -s extglob
x=./gandalf.tar.a.b.c
noext=${x%%.*([!/])}
echo "$noext"
This deletes the substring not containing a /
character, after and including the first .
character. Also works for x=/pq.12/r/gandalf.tar.a.b.c
Upvotes: 2
Reputation: 22225
If performance is not an issue, for instance something like this:
fil=$(basename "$x")
noext="$(dirname "$x")"/${fil%%.*}
Upvotes: 0
Reputation: 784938
If you want to give sed
a chance then:
x='./gandalf.tar.a.b.c'
sed -E 's~(.)\..*~\1~g' <<< "$x"
./gandalf
Or 2 step process in bash:
x="${s#./}"
echo "./${x%%.*}"
./gandalf
Upvotes: 3