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 .
CodePudding user response:
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
CodePudding user response:
If performance is not an issue, for instance something like this:
fil=$(basename "$x")
noext="$(dirname "$x")"/${fil%%.*}
CodePudding user response:
Strip the path first, then use greedy cancellation.
x=./gandalf.tar.gz
nopath=${x##*/}
noext=${nopath%%.*}
Edit: I just realized that you want the path in the outcome. Perhaps a regexp is the best way to go (if your bash version supports it):
[[ "$x" =~ ^(.*/|)(.[^.]*).*$ ]] && noext="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
Edit 2: I forgot to explain the regexp.
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.
Edit 3: 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
.