#!/bin/bash set -eu set -o pipefail save_directory="" dry_run=false warning=true function usage { retval="$1" case "$retval" in 0) ;; *) exec 1>&2 ;; esac echo "Usage: $0 --save-directory /backshift/save-directory --dry-run --skip-warning" 1>&2 echo echo "Finds duplicate metadata files and hardlinks them - the goal being to" echo "reduce disk space requirements." echo echo "Do -not- run this during a backup. Strange things can happen if you do." exit "$retval" } while [ "$#" -ge 1 ] do case "$1" in --save-directory) save_directory="$2" shift ;; --dry-run) dry_run=true ;; --skip-warning) warning=false ;; -h|--help) usage 0 ;; *) echo "$0: unrecognized option: $1" 1>&2 usage 1 ;; esac shift done case "$save_directory" in "") echo "$0: --save-directory is a required option" usage 1 ;; esac if ! cd "$save_directory" then echo "$0: cd to $save_directory failed" 1>&2 exit 1 fi if ! cd "files" then echo "$0: cd to $save_directory/files failed" 1>&2 exit 1 fi case "$warning" in true) echo "Warning: This program should not be used during a backup or expire. Data loss could result!" 1>&2 while true do echo 'Continue (y/N)?' read -r line first_character=$(echo "$line" | sed 's/^\(.\).*$/\1/' | tr '[:upper:]' '[:lower:]') case "$first_character" in y) break ;; n|"") echo Exiting. exit 0 ;; *) echo "Please enter y or n" continue ;; esac done ;; false) ;; *) echo "$0: internal error: \$warning has a strange value: $warning" 1>&2 exit 1 ;; esac # A dry run require too much RAM to complete correctly, even on a system with 32G of physmem and 33 G of swap space. # I had to manually recompile with rdfind's internal maxdepth variable set to 500 to get that far. # rdfind -dryrun "$dry_run" -makehardlinks true . case "$dry_run" in true) fdupes -r . ;; false) fdupes -rL . ;; *) echo "$0: internal error: \$dry_run has a strange value: $dry_run" 1>&2 exit 1 ;; esac