You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
2.8 KiB
Bash

#!/bin/bash
usage() {
echo "USAGE: $0 [--clobber=none|first|second] [--verbose] [--] search_dir other_dir"
}
verbose=
debug() {
if [ -n "$verbose" ]
then
echo "$@"
fi
}
clobber=none
while [ "${1:0:2}" == "--" ]
do
case $1 in
--)
break
;;
--verbose)
verbose=true
;;
--clobber=none)
;;
--clobber=first)
clobber=first
;;
--clobber=second)
clobber=second
;;
*)
>&2 echo "Unrecognized option: $1"
usage
exit 1
esac
shift
done
if (( $# != 2 ))
then
usage
exit 0
fi
from="$1"
to="$2"
hardlink-file-if-duplicate() {
if [ ! -f "$1" ]
then
debug "Not a regular file (or does not exist): $1"
return
elif [ ! -f "$2" ]
then
debug "Not a regular file (or does not exist): $2"
return
elif [ "$1" -ef "$2" ]
then
debug "Already a hardlink: $1 => $2"
return
elif ! cmp -s -- "$1" "$2"
then
debug "Files aren't identical: $1 != $2"
return
fi
# from https://unix.stackexchange.com/a/120866
if [ "$(stat --format="%h" "$2")" -gt 1 ]
then
if [ "$(stat --format="%h" "$1")" -gt 1 ]
then
case $clobber in
none)
echo "Skipping: both files have multiple hardlinks. Specify --clobber=first to delete $1 or --clobber=second to delete $2."
return
;;
first)
echo "Both files have multiple hardlinks, defaulting to $2 overwritting $1"
one_link_file="$1"
other_file="$2"
;;
second)
echo "Both files have multiple hardlinks, defaulting to $1 overwritting $2"
one_link_file="$2"
other_file="$1"
;;
esac
else
one_link_file="$1"
other_file="$2"
fi
else
one_link_file="$2"
other_file="$1"
fi
ln -v -f -- "$other_file" "$one_link_file"
}
if [ "$from" -ef "$to" ]
then
echo "WARNING: $from and $to are the same path. Exiting."
exit 2
elif [ ! -d "$from" ] || [ ! -d "$to" ]
then
debug hardlink-file-if-duplicate "$from" "$to"
hardlink-file-if-duplicate "$from" "$to"
exit
fi
if [[ "${from:0-1}" != "/" ]]
then
from="$from/"
fi
if [[ "${to:0-1}" != "/" ]]
then
to="$to/"
fi
debug "Searching $from ..."
# from https://stackoverflow.com/a/9612232
find "$from" -type f -print0 |
while IFS= read -r -d '' line; do
debug hardlink-file-if-duplicate "$line" "${line/#$from/$to}"
hardlink-file-if-duplicate "$line" "${line/#$from/$to}"
done