Skip to content

Instantly share code, notes, and snippets.

@connordavison
Last active September 21, 2015 02:09
Show Gist options
  • Save connordavison/dbefa5e17ff1b67c21ff to your computer and use it in GitHub Desktop.
Save connordavison/dbefa5e17ff1b67c21ff to your computer and use it in GitHub Desktop.
safe_rm
#!/bin/bash
SCRIPT=$(basename "$0")
DELETED=$HOME/deleted
# Ensure mandatory files/directories exist
touch $HOME/.restore.info
mkdir -p $DELETED
# Parse options
while getopts "ivr" opt; do
case $opt in
i ) INTERACTIVE=true;;
v ) VERBOSE=true;;
r ) RECURSIVE=true;;
\? ) echo "$SCRIPT: Invalid option: -$OPTARG";;
esac
done
# Push the options away so we can iterate over the files
shift $((OPTIND - 1))
# Return a status 1 if no parameters sent
if [ $# -eq 0 ]; then
echo "$SCRIPT: No filename provided." >&2
exit 1
fi
#
# confirm - Send a confirmation prompt to the user. Accepts Y/y/yes as
# affirmation.
# @param prompt The prompt to offer to the user
# @return 0 on an affirmatory, 1 on negatory, and 2 on invalid response
#
function confirm
{
local prompt=$1
local response
read -p "$prompt" response < /dev/tty
case $response in
[Yy]|yes* ) return 0;;
[Nn]|no* ) return 1;;
* ) return 2;;
esac
}
#
# safe_rm - Remove a file.
# @param file The file to delete
#
function safe_rm
{
local file=$1
local basename=$(basename $file)
if [ ! -e $file ]; then
echo "$SCRIPT: File does not exist."
return 1
fi
# Prevent self-deletion
if [ "$basename" = "safe_rm" ]; then
echo "$SCRIPT: Attempt to delete 'safe_rm' aborted."
return 1
fi
backup=$basename'_'$(ls -i $file | cut -d " " -f1)
cwd=$(readlink -f $file)
restore_info="$backup : $cwd"
[[ $VERBOSE ]] && echo "$SCRIPT: Appending '$restore_info' to '$HOME/.restore.info'."
echo $restore_info >> $HOME/.restore.info
loc=$basename'_'$(ls -i $file | cut -d " " -f1)
[[ $INTERACTIVE ]] && ! confirm "$SCRIPT: Remove file '$file'? " && return 1
mv $file $DELETED/$loc
[[ $VERBOSE ]] && echo "$SCRIPT: Removed '$file' to recycle bin."
}
# Loop through files
for files in $@; do
for file in $files; do
if [ -d $file ] ; then
if [[ $RECURSIVE ]]; then
dir=$file
[[ $INTERACTIVE ]] && ! confirm "$SCRIPT: Remove directory '$dir'? " && continue
find "$dir" -type f | while read file; do
safe_rm "$file";
done
rm -rf "$dir"
else
echo "$SCRIPT: Attempt to delete directory aborted."
fi
else
safe_rm "$file"
fi
done
done
nasatyau@DANTE [~/tmp]$ touch a b c d
nasatyau@DANTE [~/tmp]$ safe_rm a
nasatyau@DANTE [~/tmp]$ safe_rm -v b
safe_rm: Appending 'b_48761109 : /home/nasatyau/tmp/b' to '/home/nasatyau/.restore.info'.
safe_rm: Removed 'b' to recycle bin.
nasatyau@DANTE [~/tmp]$ safe_rm -i c
safe_rm: remove file 'c'? y
nasatyau@DANTE [~/tmp]$ safe_rm -iv d
safe_rm: Appending 'd_48761229 : /home/nasatyau/tmp/d' to '/home/nasatyau/.restore.info'.
safe_rm: remove file 'd'? y
safe_rm: Removed 'd' to recycle bin.
nasatyau@DANTE [~/tmp]$ ls
nasatyau@DANTE [~/tmp]$ tree
.
├── a
│   ├── a
│   ├── b
│   ├── c
│   └── e
│   ├── f
│   └── g
├── b
│   ├── a
│   └── b
└── f
3 directories, 8 files
nasatyau@DANTE [~/tmp]$ safe_rm -r a/e/
nasatyau@DANTE [~/tmp]$ cat ~/.restore.info
f_48761075 : /home/nasatyau/tmp/a/e/f
g_48761077 : /home/nasatyau/tmp/a/e/g
nasatyau@DANTE [~/tmp]$ ls ~/deleted/
f_48761075 g_48761077
nasatyau@DANTE [~/tmp]$ tree
.
├── a
│   ├── a
│   ├── b
│   └── c
├── b
│   ├── a
│   └── b
└── f
2 directories, 6 files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment