trash script to alias rm
Overall
I'm not really convinced of the value of this &quot;trashcan&quot; idea.  If deleting files doesn't actually delete them, then what's the point?  Trying to create free space would be ineffectual.  Worse, encouraging users to lean on an &quot;undelete&quot; facility will likely leave them in trouble when they move to a conventional system without such a crutch.  (Plus, it's a Good Thing to have an occasional minor accident - otherwise it's very easy to just assume that your backups are working, and never think to verify that you can actually restore from them!  I'm certainly guilty of that...)
Quoting issues
Much of your code doesn't quote expanded variables when it should.  One example:
case $file in
  -*) bypass $* ;;
  $trash/* ) bypass $* ;;
esac

This is unsafe, and needs to be written
case &quot;$file&quot; in
  -*) bypass &quot;$@&quot; ;;
  &quot;$trash&quot;/* ) bypass &quot;$@&quot; ;;
esac

There are many more similar instances; I won't list them all.
Testing for file-ness rather than existence
[ -f &quot;$file&quot; ] || error &quot;File not specified.&quot;

Do you really want this error when you ask to trash a symlink?  In fact, I think the wording of the message is poor, even for the case you think you're testing.
Pathname matching
You test whether the argument is in the &quot;trash&quot; directory with
case $file in
  $trash/* )
esac

There's other ways to refer to the same directory as &quot;$trash&quot; - in particular, a relative name from the working directory.  You'll need to canonicalise path name if you're doing this kind of comparison; possibly you might want to compare device and inode numbers for real robustness if you might have bind mounts and the like.
Echo and read
This code:
echo -n &quot;Which would you like to restore? [1]:&quot;
read user

is usually written
read -p &quot;Which would you like to restore? [1]: &quot; user

(I'm not sure that user is a good name for the version number, either).