HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashMinor

Bash script to send to recycle bin or trash

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
scriptrecyclebintrashsendbash

Problem

This is a script that emulates a recycle bin in the CLI.

You can undo your last changes and delete files

This is my first bash script so don't hesitate to bash me. Thank you for taking a look.

``
#! /bin/bash

usage(){
cat specify the recycle directory
(defaults to '.recycle' in your ~)
All other options are ignored when moving files. When removing
permanently, these options are passed to /bin/rm

EOF
}

FILES=""
VERBOSE=0
DRY=0
RESTORE=0
ERRORSTOP=0
TROOT="$HOME"
UNDO=0
RBIN=".recycle"
CURR=
pwd`
EMPTY=0
UNDOFILE=

while getopts “hvnrsued:” OPTION
do
case $OPTION in
h)
usage
exit 0
;;
v)
VERBOSE=1
;;
n)
DRY=1
;;
r)
RESTORE=1
;;
u)
UNDO=1
;;
d)
RBIN=$OPTARG
;;
e)
EMPTY=1
;;
s)
ERRORSTOP=1
;;
?)
echo "Invalid option: -$OPTARG" >&2
usage
exit 1
;;
esac
done

#setting the undo file name, will be ~/.recycle-log by default
UNDOFILE=$TROOT/$RBIN"-log"
#setting full path for the recycle bin dir
RBIN="$TROOT/$RBIN"

if [ "$VERBOSE" = 1 ]; then
echo "recycle dir: $RBIN"
echo "current dir: $CURR"
fi

# creating the recycle bin dir if it does not exist
test -d "$RBIN" || mkdir -p "$RBIN"

if [ ! -d "$RBIN" ]; then
echo "could not create the directory $RBIN" >&2
exit 1
fi

# if -u was passed, undo and exit
if [ "$UNDO" = 1 ]; then
if [ -f "$UNDOFILE" ]; then
source $UNDOFILE
rm $UNDOFILE
echo "undone" >&2
exit 0
else
echo "no undo file found, cannot undo" >&2
exit 1
fi
fi

# resetting undo file for changes to come
if [ -f "$UNDOFILE" ]; then
rm $UNDOFILE
fi

shift $(( OPTIND - 1 ))

# if -e or -u were passed, no arguments is ok
# if not, then the used should provide at least
# one filename
if [ "$EMPTY" = 0 ]; then
if [ -z

Solution


  • You don't need a space in the current shebang line. Anyway, Greg's wiki and others recommend #!/usr/bin/env bash (for portability, but I can't find a reference at the moment).



-
Any command substitutions should use "$(foo)" rather than `foo. That way, you actually get what the command returns (except for trailing newlines) rather than a whitespace-clobbered version. For example, CURR="$(pwd)", or even better:

CURR="$(pwd; echo x)"
CURR="${CURR%x}"


  • Don't use actual opening and closing quotation marks (“hvnrsued:”). This type of quotes are just regular characters in Bash, so it's as if you had added a -“ and -” option. More about quotes.



  • Some lines are not indented properly. Incorrect indentation makes the code hard to read, and in the worst case can introduce errors because of misunderstandings of context.



-
Use the safe version of all calls which support it:
command --option1 --option2 -- "$file1" "$file2". The double dashes separate options from filenames in most *nix commands, to avoid interpretation of filenames as options, or, in the worst case, acting on the wrong file. Other commands have special flags (-e, --regex in grep) to prefix other options to avoid treating the second option as another flag. Compare (untested)

printf %s -foo | grep -foo # No such file oo


with

printf %s -foo | grep -e -foo


-
echo is one of those unfortunate commands which don't have such an option. Use printf if you don't know what the input will be. Compare (untested)

string=-escape
echo "$string" # No such option -s


with

printf %s "$string"


-
Create lots of test cases. This is such a dangerous script that you'd better have some proof that complex file names created by accident or malicious users don't have an opportunity to wreak havoc. I can thoroughly recommend shunit2, which is even in the Ubuntu repositories. Example tests.

  • You should add set -o errexit -o noclobber -o nounset -o pipefail at the beginning of the file to ensure stricter error checking. Only re-enable clobbering for the smallest possible code block (i.e., the single line where you use redirection to file) if necessary.



-
Declare read-only variables as such (
help readonly, help declare) to avoid accidental modification. This should be done separately from assignment - If you do it together (declare -r foo="$(false)"`), you'll find that the exit code of the command substitution is lost. Compare

declare -r foo="$(false)"
echo $?


with

bar="$(false)"
echo $?
declare -r bar
echo $?

Code Snippets

CURR="$(pwd; echo x)"
CURR="${CURR%x}"
printf %s -foo | grep -foo # No such file oo
printf %s -foo | grep -e -foo
string=-escape
echo "$string" # No such option -s
printf %s "$string"

Context

StackExchange Code Review Q#10768, answer score: 5

Revisions (0)

No revisions yet.