简体   繁体   中英

How to remove all file extensions in bash?

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]}"

Regexp explained

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.

Note

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM