set -- *.exe stores filenames matching *.exe as positional parameters, unless there is no match. In case there is no match the result depends on the shell (see the beginning of this answer); in the POSIX shell you get the literal *.exe string as the first and only positional parameter.
If you are sure there is exactly one match then you don't need to test anything. If you are not sure then:
- check if
$# expands to 1 ([ "$#" -eq 1 ]),
- check if the alleged file exists (
[ -e "$1"]).
Then the name you're after is in $1. To translate Foo.exe to Foo.7z you need to remove exe and add 7z (${1%exe}7z).
The snippet will be like:
(
set -- *.exe
# here validate $# and/or $1 if necessary
7z a "${1%exe}7z" …
)
I used a subshell, so set does not affect the positional parameters of the main shell. Quoting is important.
Notes:
- The solution allows the match to be a directory. Any directory is also a file.
- You wrote "add all files" and then used
*.* -x!*.sh. I'm not going to nitpick by saying the exclusion contradicts "all files". There are problems though:
-x!*.sh should be quoted, so the shell never expands *. The string should be single-quoted because some shells expand ! even in double-quotes.
*.* may mean "all files" in Windows (at least with some tools), but in a Linux shell the dot strictly matches a dot. * as a filename generation pattern is closer to "all files", still not "all files".
- The solution is prone to TOCTOU. Probably the content of your directory does not change "randomly" and the solution will work. If the directory is not static then one may need to create an archive with temporary name, list its contents and parse to learn what
.exe (if any) got to the archive, finally rename the archive accordingly.
- Keep in mind filenames in Linux are case-sensitive in general; tools that work with filenames are also case-sensitive. Normally
set -- *.exe does not detect FOO.EXE. In some shells you can adjust this behavior (e.g. investigate shopt -s nocaseglob in Bash); then you would want to use ${1%[eE][xX][eE]}7z to properly deal with EXE, Exe or any other variant during name translation.