utaz: add case management sensitivity support

This commit is contained in:
2026-10-13 11:21:53 +02:00
parent 2cc767ecc2
commit 6bfc2804ab
5 changed files with 76 additions and 9 deletions
+40 -7
View File
@@ -44,6 +44,9 @@ load_conf "compress"
# -d, --delete If decompression succeeded, delete the source file
# -c, --create-dir Always create a host directory
# -n, --no-dir Never create a host directory
# -i, --ignore-case Match archive extensions case-insensitively (.ZIP, .Tar.GZ)
# -s, --case-sensitive Match archive extensions case-sensitively (overrides the
# UTAZ_DEFAULT_IGNORE_CASE configuration key)
utaz()
{
# Extractor helpers. Every one takes the archive path as $1 and an existing
@@ -156,7 +159,11 @@ utaz()
{
# A tar.zst/.tzst is untarred; a bare .zst is a single compressed file
# and is simply decompressed into the target directory.
case $1 in
# Called from utaz: "icase" is utaz's local, visible here through
# dynamic scoping. Lowercase the name so the match follows the mode.
local key=$1
[[ -n $icase ]] && key=${key,,}
case $key in
*.tar.zst|*.tzst)
tar --zstd -xf "$1" -C "$2"
;;
@@ -236,7 +243,7 @@ utaz()
)
local PARSED
PARSED=$(getopt -o hdcn --long help,delete,create-dir,no-dir -n 'utaz' -- "$@")
PARSED=$(getopt -o hdcnis --long help,delete,create-dir,no-dir,ignore-case,case-sensitive -n 'utaz' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [ $? -ne 0 ]; then
disp E "Invalid options, use \"utaz --help\" to display usage."
@@ -245,7 +252,7 @@ utaz()
# getopt emits a shell-quoted, normalised argument list ("--" terminates the
# options); re-evaluating it restores the arguments with spaces and quotes
# intact. Declared local so flags never leak in from the caller's environment.
local willrm="" createdir="" nodir=""
local willrm="" createdir="" nodir="" icase="" csens=""
eval set -- "$PARSED"
while true; do
case "$1" in
@@ -257,7 +264,9 @@ utaz()
printf "\t-h, --help\t\tDisplay that help screen\n"
printf "\t-d, --delete\t\tIf decompression succeeded, delete the source file\n"
printf "\t-c, --create-dir\tAlways create a host directory\n"
printf "\t-n, --no-dir\t\tNever create a host directory\n\n"
printf "\t-n, --no-dir\t\tNever create a host directory\n"
printf "\t-i, --ignore-case\tMatch archive extensions case-insensitively\n"
printf "\t-s, --case-sensitive\tMatch archive extensions case-sensitively (default)\n\n"
printf "Supported archive format:\n"
printf "\t- zip\n"
printf "\t- tar.gz, .tgz\n"
@@ -290,6 +299,14 @@ utaz()
nodir=1
shift
;;
-i|--ignore-case)
icase=1
shift
;;
-s|--case-sensitive)
csens=1
shift
;;
--)
shift
break
@@ -319,6 +336,16 @@ utaz()
return 1
}
# Extension matching: the flags win over the configured default. After this
# block "icase" is non-empty if and only if matching is case-insensitive.
[[ -n $icase && -n $csens ]] && {
disp E "The --ignore-case and --case-sensitive options are mutually exclusive."
return 1
}
if [[ -z $icase && -z $csens && ${UTAZ_DEFAULT_IGNORE_CASE:-0} -eq 1 ]]; then
icase=1
fi
# Loop variables are local: this function lives in the interactive shell.
local zitem f
for zitem in "${FILES[@]}"; do
@@ -343,13 +370,19 @@ utaz()
fi
for f in "${targets[@]}"; do
# "key" is the name the extension patterns are matched against:
# lowercased in ignore-case mode, untouched otherwise.
local key=$f
[[ -n $icase ]] && key=${f,,}
# Host directory name: archive name without its extension. A
# trailing ".tar" is dropped too, so foo.tar.gz gives "foo", not
# "foo.tar".
# "foo.tar". The ".tar" test uses "key" so it follows the case mode
# (the extension is 4 characters either way).
local dir="${f%.*}"
[[ $dir == *.tar ]] && dir="${dir%.tar}"
[[ ${key%.*} == *.tar ]] && dir="${dir%.*}"
local extractor=""
case "$f" in
case "$key" in
*.zip)
extractor="_ununzip"
;;