+#!/bin/bash
+# Desc: Deduplicates files within a CBZ file
+# Usage: cbz_dedup.sh [CBZ file]
+# Example: cbz_dedup.sh input.cbz
+# Version: 0.0.5
+# Depends: jdupes 1.27.3, unzip 6.00 by Debian
+
+
+yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
+die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
+must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
+showUsage() {
+ # Desc: Display script usage information
+ # Usage: showUsage
+ # Version 0.0.2
+ # Input: none
+ # Output: stdout
+ # Depends: GNU-coreutils 8.30 (cat)
+ cat <<'EOF'
+ USAGE:
+ cbz_dedup.sh [FILE]
+
+ EXAMPLE:
+ cbz_dedup.sh input.cbz
+EOF
+}; # Display information on how to use this script.
+main() {
+ fout="output.cbz";
+
+ # Check args
+ if [[ $# -ne 1 ]]; then showUsage; die "FATAL:Invalid arg count (should be 1):$#"; fi;
+ re1='\.cbz$';
+ if [[ ! "$1" =~ $re1 ]]; then showUsage; die "FATAL:Not a .cbz file:$1"; fi;
+ if [[ ! -f "$1" ]]; then die "FATAL:Not a file:$1"; fi;
+ fin="$1";
+ dir_tmp="$(mktemp -d)";
+ if [[ ! -d "$dir_tmp" ]]; then die "FATAL:Could not make temporary directory:${dir_tmp}"; fi;
+ trap 'rm -rf "${dir_tmp}"' EXIT;
+ pout="${dir_tmp}/${fout}";
+
+ # Check depends
+ for _cmd in unzip zip jdupes; do
+ if ! command -v "$_cmd" 1>/dev/random 2>&1; then
+ die "FATAL:Missing app:${_cmd}";
+ fi;
+ done;
+
+ # Extract CBZ to temp dir
+ must unzip "$fin" -x / -d "$dir_tmp";
+
+ # Dedupe with jdupes
+ ## Check size before
+ tmp_size1="$(du -bd0 "$dir_tmp" | cut -f1; )";
+ must jdupes -dN "${dir_tmp}";
+ ## Check size after
+ tmp_size2="$(du -bd0 "$dir_tmp" | cut -f1; )";
+
+ # Replace CBZ if size changed
+ if [[ "$tmp_size1" -eq "$tmp_size2" ]]; then yell "STATUS:No deduplication detected."; return 0; fi;
+
+ ## Recreate CBZ
+ must zip -j "$pout" "${dir_tmp}"/*;
+
+ ## Preserve original CBZ
+ must mv -n "$fin" "${fin%.*}_original.cbz";
+
+ ## Move deduped CBZ
+ must mv -n "$pout" "$fin";
+
+ return 0;
+};
+
+main "$@";