--- /dev/null
+#!/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 "$@";
#!/bin/bash
# Desc: Collects .jpg/jpeg files from a Calibre .htmlz file into .cbz files
-# Version: 0.1.0
+# Version: 0.1.2
# Depends: jdupes 1.27.3
for fin in ./*.htmlz; do
dout="${fin%.*}";
unzip "$fin" -x / -d "$dout";
pushd "$dout";
- mapfile -t images < <(cat index.html | grep -E "(.jpg|.jpeg)" | sed -E -e 's#.+(images/[0-9]+.(jpeg|jpg)).+#\1#' | uniq; );
- dout="./output";
- if [[ -d "$dout" ]]; then
- rm -r "$dout";
+ mapfile -t images < <(cat index.html | grep -E "(.jpg|.jpeg|.png)" | sed -E -e 's#.+(images/[0-9]+.(jpeg|jpg|png)).+#\1#' | uniq; );
+ dout2="./output";
+ if [[ -d "$dout2" ]]; then
+ rm -r "$dout2";
fi;
- mkdir "$dout";
+ mkdir "$dout2";
n=1;
for path in "${images[@]}"; do
- fnew="${dout}/$(printf "%06d" "$n").jpg";
+ fnew="${dout2}/$(printf "%06d" "$n").jpg";
cp "$path" "$fnew";
((n++));
done;
# Add cover file if present
if [[ -f cover.jpg ]]; then
- cp -n cover.jpg "${dout}/000000.jpg";
+ cp -n cover.jpg "${dout2}/000000.jpg";
fi;
# Remove duplicate images
if command -v jdupes 1>/dev/random 2>&1; then
- jdupes -dN "$dout";
+ jdupes -dN "$dout2";
fi;
faout="output.cbz";
if [[ -f "$faout" ]]; then
rm "$fout";
fi;
- zip -j output.cbz "$dout"/*;
+ zip -j output.cbz "$dout2"/*;
) &
done;
wait && echo "STATUS:Finished." 1>&2;