Skip to content

Instantly share code, notes, and snippets.

@thingsiplay
Last active February 12, 2025 14:25
Show Gist options
  • Save thingsiplay/889cb2899f35405e10839112f5181ab3 to your computer and use it in GitHub Desktop.
Save thingsiplay/889cb2899f35405e10839112f5181ab3 to your computer and use it in GitHub Desktop.
toarchive - Create one archive for each file or folder (Bash using 7z)
#!/usr/bin/env bash
supported_ext=("7z" "zip")
help() {
cat <<EOF
toarchive ext [options] files...
toarchive zip -f -k *.smc
Convert each file to an archive using 7z, similar to gzip.
options:
ext archive extension and format to create, supported: ${supported_ext[*]}
-r remove original input file on success
-R delete original input files and directory recursively on success
-f force create and overwrite existing archive
Careful: Option -R will make use of system command 'rm -r'.
The rest of the options starting with a "-" will be directly forwarded to 7z.
EOF
}
# Create one archive for each file or folder.
if [ "${#}" -eq 0 ]; then
help
elif [ "${1}" == 'help' ] || [ "${1}" == '--help' ] || [ "${1}" == '-h' ]; then
help
else
ext=''
for se in "${supported_ext[@]}"; do
if [ "${se}" == "${1}" ]; then
ext="${1}"
shift
break
fi
done
if [ "${ext}" == '' ]; then
echo "'${1}' is not in list of supported formats: ${supported_ext[*]}"
exit 1
fi
opt=()
stop_parse=false
force_write=false
delete_files=false
recursive_delete_dirs=false
for arg in "${@}"; do
if [ ! "${stop_parse}" == true ]; then
if [ "${arg}" == "--" ]; then
stop_parse=true
opt+=(--)
continue
elif [ "${arg}" == '-r' ]; then
delete_files=true
continue
elif [ "${arg}" == '-R' ]; then
recursive_delete_dirs=true
continue
elif [ "${arg}" == '-f' ]; then
force_write=true
continue
elif [[ "${arg}" =~ ^- ]]; then
opt+=("${arg}")
continue
fi
fi
if [ "${arg}" == '' ]; then
echo "Input path cannot be empty."
exit 1
fi
input_file="$(readlink --canonicalize --quiet "${arg}")"
if ! [ -e "${input_file}" ]; then
echo "Input path must point to an existing file or directory: '${input_file}'"
exit 1
fi
output_file="${input_file}.${ext}"
if [ "${force_write}" == true ] || ! [ -f "${output_file}" ]; then
7z a "${opt[@]}" "${output_file}" "${input_file}"
if [ "${recursive_delete_dirs}" == true ] &&
[ -f "${output_file}" ]; then
rm --recursive --dir -- "${input_file}"
elif [ "${delete_files}" == true ] &&
[ -f "${output_file}" ] &&
[ -f "${input_file}" ]; then
rm -- "${input_file}"
fi
fi
done
fi
#!/usr/bin/env bash
# Create one archive for each file or folder.
if [ "${#}" -eq -1 ]; then
echo "toarchive ext files..."
echo "toarchive zip *.smc"
else
ext="${1}"
shift
opt=()
stop_parse=false
for arg in "${@}"; do
if [ ! "${stop_parse}" == true ]; then
if [ "${arg}" == "--" ]; then
stop_parse=true
opt+=(--)
continue
elif [[ "${arg}" =~ ^- ]]; then
opt+=("${arg}")
continue
fi
fi
file="${arg}"
7z a "${opt[@]}" "${file}.${ext}" "${file}"
done
fi
@thingsiplay
Copy link
Author

I have added a new version of the script. The old one is renamed to 'toarchive-old'.

The new script has some guard rails and more checks. Also original files can be removed automatically on success, like gzip does. But an option -r must be explicitly given here, like toarchive zip -r file.txt. Directories can be removed too, but the option uppercase -R is required here, as in toarchive zip -R my_dir. Have in mind this will use rm -r system command. Although some guard rails are in place to prevent massive fail, you should be very careful. Note that no file is removed, if -r or -R are not used at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment