*Self-review for the follow-up question, which I will post in the following days.* # Treat unset variables as an error when substituting Add this to the beginning of the script: set -o nounset # `[ "$#" -eq 0 ]` instead of `[ -z "$1" ]` It seems testing number of arguments is a better approach than testing if the first argument is set. Also, I added: [ "$#" -gt 1 ] && echo "Multiple arguments are not supported!" && exit 1 for an obvious reason. # As pointed out by Janos, put password file path into variable And put it in the beginning of the script (maybe with a comment). # In order to compress many directories with the same password, # I decided to create a password file to avoid too many annoying prompts passwd_file="/home/vlastimil/.blablablabla" # Test for the existence of the password file It may happen that you migrate to a different platform and / or accidentally delete the file. [ ! -f "$passwd_file" ] && echo "The password file does not exist!" && exit 1 # You should also test for existence of the processed files Like this, the comments are optional: # TAR is archiving the directory into the following temporary file, # it gets deleted on successful processing [ -f "${backup_file}" ] && echo "File ${backup_file} exists, exiting." && exit 1 # XZ is compressing the archive into the following temporary file, # it gets deleted on successful processing [ -f "${backup_file}.xz" ] && echo "File ${backup_file}.xz exists, exiting." && exit 1 # OpenSSL is decrypting the file (for verification) into the following temporary file, # it gets deleted on successful processing [ -f "${backup_file}.xz.dec" ] && echo "File ${backup_file}.xz.dec exists, exiting." && exit 1 # OpenSSL is encrypting the compressed file into the following permanent file, # this is the result of successful processing [ -f "${backup_file}.xz.enc" ] && echo "File ${backup_file}.xz.enc exists, exiting." && exit 1 # SHA512SUM is computing a hash sum of the encrypted file into the following permanent file, # this is the result of successful processing [ -f "${backup_file}.xz.enc.SHA512SUM" ] && echo "File ${backup_file}.xz.enc.SHA512SUM exists, exiting." && exit 1 # Define all common colors (optional) It happens one might like a change and / or later wants to re-define the styling. So this may be good idea, just comment out the colors that you don't use. red=$(tput setaf 1) blue=$(tput setaf 4) cyan=$(tput setaf 6) green=$(tput setaf 2) white=$(tput setaf 7) yellow=$(tput setaf 3) magenta=$(tput setaf 5) # As pointed out by Janos, color definitions should be renamed > I would rename bold_red and bold_yellow to be more about the purpose than presentation. And I agree: action_number_color="${bold}${red}" action_color="${bold}${yellow}" file_color="${bold}${white}" success_color="${bold}${green}" # Again, as pointed out by Janos, there should be a helper printing function > A helper function would be more convenient to print the headers for the steps, instead of blocks of `echo`s. Like this, I added some leading and trailing coloring: print_action() { echo echo "${action_number_color}$1${no_color}" echo } # There could be a helper error function too For instance: print_error() { echo echo "$1" exit 1 } # There are too long lines of strings Both in the code, and in the output. It could be simplified for example: print_action "1/7:${action_color} TAR is archiving the directory ${file_color}${dir}${action_color} into ${file_color}${backup_file}" # `tar --verify` for enhanced integrity The man page says: > -W, --verify: attempt to verify the archive after writing it Just to note: I take it, this option is only usable when creating the archive, and not if later checking the integrity. # `if`s can be completely pulled out of the whole script More importantly, it makes the script more readable this way: tar --create --file="${backup_file}" "$1" --totals --verify || print_error "TAR failed to archive the directory!" # Too long lines of code could be split There were also places where the code itself could be formatted in two lines simply with the already present `|` (pipe), which acts as delimiter too. pv --progress --timer --eta --rate --average-rate --bytes "${backup_file}.xz" | openssl enc -aes-256-cbc -md sha256 -salt -out "${backup_file}.xz.enc" -pass file:"$passwd_file" 2> /dev/null || print_error "OpenSSL failed to encrypt the compressed file!" # Average rate could further be added to the `pv` statement As shown above, this could be somewhat useful to me at least if the file is very large. # Remove `-W` parameter from `pv` The `--wait` parameter is useless in case like this, where we are not waiting for user input. What's more, it caused `pv` not to output anything on small files. # As pointed out by Janos, remove the `sha512sum --check` Not only it is useless in this case, but it takes a few seconds. Better yet, you could replace it with showing the SHA-512 hash sum like this: awk '{ print $1 }' "${backup_file}.xz.enc.SHA512SUM" # Use `cmp` with `--silent` parameter As you are not interested in actual differences in those files, and only wish to check the return value of `cmp`, this is the right way: cmp --silent "${backup_file}.xz" "${backup_file}.xz.dec" && echo "Files are identical." || print_error "Failed to compare files!" # Re-write awkward texts I have re-written most of them, but one example: > Comparing your un-encrypted, compressed, archived, directory file could sound better as > CMP is comparing the un-encrypted compressed file # Current code looks like this #!/bin/sh # Treat unset variables as an error when substituting set -o nounset [ "$#" -eq 0 ] && echo "You need to give me one directory!" && exit 1 [ "$#" -gt 1 ] && echo "Multiple arguments are not supported!" && exit 1 [ ! -d "$1" ] && echo "This is not a directory!" && exit 1 [ ! -w "$PWD" ] && echo "The current directory is not writable by you!" && exit 1 # In order to compress many directories with the same password, # I decided to create a password file to avoid too many annoying prompts passwd_file="/home/vlastimil/.blablablabla" [ ! -f "$passwd_file" ] && echo "The password file does not exist!" && exit 1 dir=$(basename "$1") today=$(date +%Y-%m-%d) backup_dir="${dir}_${today}" # backup_dir="${dir}" backup_file="${backup_dir}.tar" # TAR is archiving the directory into the following temporary file, # it gets deleted on successful processing [ -f "${backup_file}" ] && echo "File ${backup_file} exists, exiting." && exit 1 # XZ is compressing the archive into the following temporary file, # it gets deleted on successful processing [ -f "${backup_file}.xz" ] && echo "File ${backup_file}.xz exists, exiting." && exit 1 # OpenSSL is decrypting the file (for verification) into the following temporary file, # it gets deleted on successful processing [ -f "${backup_file}.xz.dec" ] && echo "File ${backup_file}.xz.dec exists, exiting." && exit 1 # OpenSSL is encrypting the compressed file into the following permanent file, # this is the result of successful processing [ -f "${backup_file}.xz.enc" ] && echo "File ${backup_file}.xz.enc exists, exiting." && exit 1 # SHA512SUM is computing a hash sum of the encrypted file into the following permanent file, # this is the result of successful processing [ -f "${backup_file}.xz.enc.SHA512SUM" ] && echo "File ${backup_file}.xz.enc.SHA512SUM exists, exiting." && exit 1 bold=$(tput bold) no_color=$(tput sgr0) red=$(tput setaf 1) #blue=$(tput setaf 4) #cyan=$(tput setaf 6) green=$(tput setaf 2) white=$(tput setaf 7) yellow=$(tput setaf 3) #magenta=$(tput setaf 5) action_number_color="${bold}${red}" action_color="${bold}${yellow}" file_color="${bold}${white}" success_color="${bold}${green}" print_action() { echo echo "${action_number_color}$1${no_color}" echo } print_error() { echo echo "$1" exit 1 } #------------------------------------------------------------------------------------------------------------------ print_action "1/7:${action_color} TAR is archiving the directory ${file_color}${dir}${action_color} into ${file_color}${backup_file}" tar --create --file="${backup_file}" "$1" --totals --verify || print_error "TAR failed to archive the directory!" #------------------------------------------------------------------------------------------------------------------ print_action "2/7:${action_color} XZ is compressing the archive ${file_color}${backup_file}${action_color} into ${file_color}${backup_file}.xz" xz --format=xz --check=sha256 -9 --threads=8 --keep --verbose --extreme "${backup_file}" || print_error "XZ failed to compress the backup file!" #------------------------------------------------------------------------------------------------------------------ print_action "3/7:${action_color} OpenSSL is encrypting the compressed file ${file_color}${backup_file}.xz${action_color} into ${file_color}${backup_file}.xz.enc" pv --progress --timer --eta --rate --average-rate --bytes "${backup_file}.xz" | openssl enc -aes-256-cbc -md sha256 -salt -out "${backup_file}.xz.enc" -pass file:"$passwd_file" 2> /dev/null || print_error "OpenSSL failed to encrypt the compressed file!" #------------------------------------------------------------------------------------------------------------------ print_action "4/7:${action_color} SHA512SUM is computing a hash sum of the encrypted file ${file_color}${backup_file}.xz.enc${action_color} into ${file_color}${backup_file}.xz.enc.SHA512SUM" sha512sum --binary "${backup_file}.xz.enc" > "${backup_file}.xz.enc.SHA512SUM" || print_error "SHA512SUM failed to compute the hash sum!" #------------------------------------------------------------------------------------------------------------------ awk '{ print $1 }' "${backup_file}.xz.enc.SHA512SUM" #------------------------------------------------------------------------------------------------------------------ print_action "5/7:${action_color} OpenSSL is decrypting the file (for verification) ${file_color}${backup_file}.xz.enc${action_color} into ${file_color}${backup_file}.xz.dec" pv --progress --timer --eta --rate --average-rate --bytes "${backup_file}.xz.enc" | openssl enc -aes-256-cbc -md sha256 -salt -out "${backup_file}.xz.dec" -d -pass file:"$passwd_file" 2> /dev/null || print_error "OpenSSL failed to decrypt the encrypted file!" #------------------------------------------------------------------------------------------------------------------ print_action "6/7:${action_color} CMP is comparing the un-encrypted compressed file ${file_color}${backup_file}.xz${action_color} with ${file_color}${backup_file}.xz.dec" cmp --silent "${backup_file}.xz" "${backup_file}.xz.dec" && echo "Files are identical." || print_error "Failed to compare files!" && { print_action "7/7:${action_color} Cleaning up" rm "${backup_file}" && echo "${backup_file} removed" rm "${backup_file}.xz" && echo "${backup_file}.xz removed" rm "${backup_file}.xz.dec" && echo "${backup_file}.xz.dec removed" echo echo "${success_color}Your directory ${file_color}${dir}${success_color} has been successfully stored as ${file_color}${backup_file}.xz.enc${no_color}" exit 0 } # And how it appears in Cygwin [![backupdir script output look in Cygwin][1]][1] [1]: https://i.sstatic.net/UAPLb.png