129 lines
2.8 KiB
Bash
Executable File
129 lines
2.8 KiB
Bash
Executable File
#!/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
|