224 lines
6.1 KiB
Bash
Executable File
224 lines
6.1 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# (C) Copyright Collin Doering 2011
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# File: link-conf.sh
|
|
# Author: Collin J. Doering <rekahsoft@gmail.com>
|
|
# Date: Jun 4, 2011
|
|
|
|
# TODO: * add support for a 'interactive' option [ -i | --interactive ]
|
|
# * add support for a link-to option so you can link the given config-dir files to
|
|
# somewhere other then $HOME
|
|
|
|
# lnfrec takes:
|
|
# $1: the config dir in question
|
|
# $2: the current directory in the recursive call (used internally to recurse the config dir)
|
|
# $3: boolean specifying option relink
|
|
# $4: boolean specifying option clean
|
|
# $5: boolean specifying option verbose
|
|
# $6: boolean specifying option force
|
|
# $7: boolean specifying option dry
|
|
function lnfrec () {
|
|
# for each file in $1 directory do link (default), relink ($3) or clean ($4) along with options
|
|
# verbose ($5) and force ($6)
|
|
for f in `ls -aA $1/$2`; do
|
|
case "$f" in
|
|
.)
|
|
;;
|
|
..)
|
|
;;
|
|
*/.)
|
|
;;
|
|
*/..)
|
|
;;
|
|
*~)
|
|
;;
|
|
.git)
|
|
;;
|
|
.gitignore)
|
|
;;
|
|
*)
|
|
# If the current file being recursed on from the given config dir ($1) is a directory
|
|
if [[ -d "$1$2/$f" ]]; then
|
|
# If the file currently being recursed on from the config dir ($1) in $HOME is not a directory
|
|
# (that is $HOME$2/$f); then create the directory $HOME$2/$f
|
|
if [[ ! -d "$HOME$2/$f" ]]; then
|
|
$5 && echo "Creating dir $HOME$2/$f"
|
|
! $7 && mkdir "$HOME$2/$f"
|
|
fi
|
|
# recurse further into config dir to $1$2/$f
|
|
lnfrec "$1" "$2/$f" $3 $4 $5 $6 $7
|
|
# If the current file being recursed on from the given config dir ($1) in $HOME is not a directory
|
|
# and is not a file or a link, then create a hardlink from $1$2/$f to $HOME$2/$f
|
|
elif [[ ! -e "$HOME$2/$f" && ! -L "$HOME$2/$f" ]]; then
|
|
$5 && echo "Linked $1$2/$f -> $HOME$2/$f"
|
|
! $7 && ln "$1$2/$f" "$HOME$2/$f"
|
|
# Otherwise: the file exists ($HOME$2/$f)
|
|
else
|
|
NUM_LINKS=$(ls -al "$HOME$2/$f" | cut -d' ' -f2)
|
|
|
|
# If the relink option is set
|
|
if $3; then
|
|
# check if the config file $HOME$2/$f has more then one hardlink; if so then relink
|
|
if [[ $NUM_LINKS -gt 1 ]]; then
|
|
$5 && echo "Re-linking $1$2/$f -> $HOME$2/$f"
|
|
! $7 && rm "$HOME$2/$f"
|
|
! $7 && ln "$1$2/$f" "$HOME$2/$f"
|
|
# if the force option is set (along with the relink option)
|
|
elif $6; then
|
|
echo "Warning! Removing regular file $HOME$2/$f"
|
|
! $7 && rm "$HOME$2/$f"
|
|
$5 && echo "Re-linking $1$2/$f -> $HOME$2/$f"
|
|
! $7 && ln "$1$2/$f" "$HOME$2/$f"
|
|
else
|
|
$5 && echo "$HOME$2/$f only has one file reference! Skipping.."
|
|
fi
|
|
# If the clean option is set
|
|
elif $4; then
|
|
# Check if the config file $HOME$2/$f has more then one hardlink; if so then clean the file from home
|
|
if [[ $NUM_LINKS -gt 1 ]]; then
|
|
$5 && echo "Cleaning $HOME$2/$f"
|
|
! $7 && rm "$HOME$2/$f"
|
|
# If the force option is set (along with clean)
|
|
elif $6; then
|
|
echo "Warning! Forcing removal of $HOME$2/$f"
|
|
$5 && echo "Cleaning $HOME$2/$f"
|
|
! $7 && rm "$HOME$2/$f"
|
|
else
|
|
$5 && echo "$HOME$2/$f only has one file reference! Skipping.."
|
|
fi
|
|
else
|
|
$5 && echo "$HOME$2/$f already linked! Skipping.."
|
|
fi # will fault if not given proper arguments! Internal usage only!
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
function displayHelp () {
|
|
echo "Usage: link-conf [-r|--relink] [-f|--force] [-c|--clean] [-v|--verbose] [-d|--dry] [-h|--help] config-dir"
|
|
}
|
|
|
|
# Option variables set when parsing cli parameters
|
|
RELINK=false
|
|
CLEAN=false
|
|
VERBOSE=false
|
|
FORCE=false
|
|
DRY=false
|
|
CONFIG_DIR=""
|
|
|
|
# Use getopt to parse given cli arguments
|
|
args=`getopt -n link-conf -o rcfvdh -l relink,clean,force,verbose,dry,help -- $*`
|
|
if [ ! $? ]; then
|
|
echo "Failed to parse arguments!"
|
|
displayHelp
|
|
exit 1
|
|
fi
|
|
|
|
# Set arguments to the new ones done by using getopt
|
|
set -- $args
|
|
|
|
while true; do
|
|
case "$1" in
|
|
-r | --relink)
|
|
if $CLEAN; then
|
|
echo "Error! Cannot specify relink and clean at once!"
|
|
exit 1
|
|
elif [ !$RELINK ]; then
|
|
RELINK=true
|
|
else
|
|
echo "Error! -r | --relink used more then once!"
|
|
exit 1
|
|
fi
|
|
;;
|
|
-c | --clean)
|
|
if $RELINK; then
|
|
echo "Error! Cannot specify relink and clean at once!"
|
|
exit 1
|
|
elif [ !$CLEAN ]; then
|
|
CLEAN=true
|
|
else
|
|
echo "Error! -c | --clean used more then once!"
|
|
exit 1
|
|
fi
|
|
;;
|
|
-v | --verbose)
|
|
if [ !$VERBOSE ]; then
|
|
VERBOSE=true
|
|
else
|
|
echo "Error! -v | --verbose used more then once!"
|
|
exit 1
|
|
fi
|
|
;;
|
|
-f | --force)
|
|
if [ !$FORCE ]; then
|
|
FORCE=true
|
|
else
|
|
echo "Error! -f | --force used more then once!"
|
|
exit 1
|
|
fi
|
|
;;
|
|
-d | --dry)
|
|
if [ !$DRY ]; then
|
|
DRY=true
|
|
else
|
|
echo "Error! -d | --dry used more then once!"
|
|
exit 1
|
|
fi
|
|
;;
|
|
-h | --help)
|
|
displayHelp
|
|
exit 0
|
|
;;
|
|
--)
|
|
shift
|
|
for arg; do
|
|
maybe_dir=$(echo $arg | sed "s/^\([\']\)\(.*\)\1\$/\2/g")
|
|
if [ "$CONFIG_DIR" == "" ]; then
|
|
if [[ -d "$maybe_dir" ]]; then
|
|
CONFIG_DIR="$maybe_dir"
|
|
else
|
|
echo "Error! The path given \"$maybe_dir\" is not a valid directory!"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "Error! More then one config dir was given!"
|
|
displayHelp
|
|
exit 1
|
|
fi
|
|
done
|
|
break
|
|
;;
|
|
*)
|
|
echo "Internal error!"
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# Notify the user if it is a dry run
|
|
if $DRY; then
|
|
echo "Dry run.."
|
|
fi
|
|
|
|
# Run the recursive hard linking algorithm
|
|
lnfrec "$CONFIG_DIR" "" $RELINK $CLEAN $VERBOSE $FORCE $DRY
|
|
|
|
# exit gracefully
|
|
exit 0
|