This script implements a command line level trashcan system.
Designed to work around rm
doing the bits needed to implement a trashcan system at command line level. Any user flags hands the request over to rm
. This means rm -f
will still delete a file with no recovery. Prevents execution by root as too many dependencies at superuser level. Deployment by adding aliases rm=trash
and rmoops=untrash
. Only implemented on files, does not cater for directories.
Appreciate any and all suggestions from formatting, expansion of the idea to glaring issues. Looking for an experienced eye to pin point potential issues.
/usr/local/bin/trash
#!/bin/bash
#
# Trashcan script
# alias rm=trash
#
error() {
echo $1
exit 1
}
bypass() {
exec rm $*
}
file="$1"
trash=~/.trash
keep=5
## bypass scenarios
# root user
[ "$(id -u)" = "0" ] && error "Please do not run as root user."
# special cases
case $file in
-*) bypass $* ;;
$trash/* ) bypass $* ;;
esac
# only single filename supported
[ $# -gt 1 ] && bypass $*
# can we access the file?
[ -f "$file" ] || error "File not specified."
# move existing versions out of the way
ls $trash/$file.version.* 2>/dev/null | tac | while read name; do
version=$((${name##*.}+1))
# keep the only the last number of versions
if [ $version -gt $keep ]; then
rm $name || error "Unable to remove file $name."
else
mv $name $trash/$file.version.$version || error "Unable to move version $version."
fi
done
# move file into trash (volume friendly)
cp --preserve $file $trash/$file.version.1 || error "Unable to trash your file."
rm -f $file || error "Unable to cleanup the file."
exit 0
/usr/local/bin/untrash
#!/bin/bash
#
# Restore files from Trashcan
# alias rmoops=untrash
#
error() {
echo $1
exit 1
}
file="$1"
trash=~/.trash
keep=5
## bypass scenarios
# root user
[ "$(id -u)" = "0" ] && error "Please do not run as root user."
# any flags so rm -rf actually does it
case $file in
-*) error "Flags are not supported." ;;
$trash/*) error "You cant restore from trash directly." ;;
esac
# only single filename supported
[ $# -ne 1 ] && error "File not specified."
version=0
# find latest version
for name in `ls $trash/$file.version.* 2>/dev/null | tac`
do
version=${name##*.}
break
done
[ $version -gt 0 ] || error "Sorry I cannot find your file in the trash."
echo "I have versions 1 to $version, 1 being the most recent."
echo -n "Which would you like to restore? [1]:"
read user
[ -n "$user" ] || user=1
# check we have the actual file
[ -f $trash/$file.version.$user ] || error "Sorry I cannot find that version."
# move existing file out of the way
[ -f $file ] && mv $file $file.old
# restore the file
cp $trash/$file.version.$user $file || error "Unable to restore file."
echo Version $user restored.
exit 0