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.abc
which have many more extensions.
I just need the part before the first .
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
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.abc
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. Eg
x="/foo/bar/.myinitfile.sh"
becomes /foo/bar/.myinitfile
.
If performance is not an issue, for instance something like this:
fil=$(basename "$x")
noext="$(dirname "$x")"/${fil%%.*}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.