170 lines
3.9 KiB
Bash
Executable file
170 lines
3.9 KiB
Bash
Executable file
#!/bin/sh
|
|
# cause plain rm wasn't good enough
|
|
# auto selects what trash directory to put files in if rmtrash is available
|
|
# otherwise, uses rm
|
|
|
|
set -eu
|
|
|
|
rm='rm'
|
|
|
|
err_differing_filesystems() {
|
|
echo 'Error: some files are apart of different filesystems.' >&2
|
|
# shellcheck disable=SC2016
|
|
echo 'Either set RM=rm to force not using `trash`, or remove the files individually' >&2
|
|
}
|
|
|
|
fs(){
|
|
df "$1" | sed '1d' | cut -d ' ' -f 1
|
|
}
|
|
|
|
dbg() {
|
|
echo "$@" >&2
|
|
}
|
|
|
|
rm_warning() {
|
|
echo 'WARNING: using rm - NOT trash. Files will be PERMINANTLY DELETED!' >&2
|
|
printf '%s' "Type Y to continue: " >&2
|
|
read -r confirm
|
|
if [ "$confirm" != 'Y' ]; then
|
|
printf '\n'
|
|
exit 1
|
|
fi
|
|
echo 'Waiting 3 seconds before continuing.' >&2
|
|
sleep 3
|
|
}
|
|
|
|
rm_custom_warning() {
|
|
echo 'WARNING: using custom rm command: '"$rm" >&2
|
|
echo 'This might NOT use the trash'
|
|
echo ''
|
|
echo 'Waiting 5 seconds before continuing.' >&2
|
|
sleep 5
|
|
}
|
|
|
|
err_no_trashdirs() {
|
|
echo 'Error: No trash directorys with matching filesystems are available.' >&2
|
|
echo 'Please set TRASH_DIRS to a colon-separated list of your preferred trash directories.' >&2
|
|
}
|
|
|
|
usage() {
|
|
echo "Wrapper for rm and rm-trash commands"
|
|
echo ""
|
|
echo "Environment:"
|
|
echo " RM Force using a particular rm command."
|
|
# shellcheck disable=SC2016
|
|
echo ' TRASH_DIRS What directories to use as trash locations for `trash`.'
|
|
echo ' DRY Dry run: print the rm command instead of executing it.'
|
|
echo ""
|
|
echo "Usage:"
|
|
echo " ${0##*/} [ARGS]"
|
|
echo ""
|
|
echo "Where ARGS is the argument list corresponding to the rm command to be used."
|
|
echo ""
|
|
echo "Current selection for rm command: $which_rm"
|
|
}
|
|
|
|
do_rm() {
|
|
if [ "${DRY:-false}" = true ]; then
|
|
echo "$rm" "$@"
|
|
else
|
|
"$rm" "$@"
|
|
fi
|
|
}
|
|
|
|
do_rmnormal() {
|
|
# shellcheck disable=SC2209
|
|
rm=rm
|
|
rm_warning
|
|
do_rm "$@"
|
|
}
|
|
|
|
do_rmcustom() {
|
|
# check if we have been given an rm command
|
|
rm="$RM"
|
|
rm_custom_warning
|
|
do_rm "$@"
|
|
}
|
|
|
|
do_rmtrash() {
|
|
# get trash directories
|
|
trash_default_fallback="$HOME"/.local/share
|
|
trash_default="${XDG_DATA_HOME:-"$trash_default_fallback"}/Trash"
|
|
trashdirs="${TRASH_DIRS:-"$trash_default"}"
|
|
|
|
# if trash is available, use it
|
|
rm='trash'
|
|
fs1=''
|
|
# validate that all files are on the same filesystem
|
|
for a; do
|
|
if [ -e "$a" ]; then
|
|
fs="$(fs "$a")"
|
|
if [ -z "$fs1" ]; then
|
|
fs1="$fs"
|
|
# this will only run the first time through the loop
|
|
continue
|
|
fi
|
|
# ensure all files are on the same filesystem
|
|
if [ "$fs1" != "$fs" ]; then
|
|
err_differing_filesystems
|
|
exit 1
|
|
fi
|
|
fi
|
|
done
|
|
if [ "$fs1" != '' ]; then
|
|
# if we get here, we have validated that all the files are on the same filesystem
|
|
trashdir=''
|
|
found_trash=false
|
|
while [ "$trashdirs" != "$trashdir" ]; do
|
|
trashdir="${trashdirs%%:*}"
|
|
trashdirs="${trashdirs#"$trashdir":}"
|
|
fs="$(fs "$trashdir")"
|
|
if [ "$fs" = "$fs1" ]; then
|
|
found_trash=true
|
|
break
|
|
fi
|
|
done
|
|
if [ "$found_trash" = true ]; then
|
|
set -- --trash-dir "$trashdir" "$@"
|
|
else
|
|
err_no_trashdirs
|
|
exit 1
|
|
fi
|
|
fi
|
|
echo "trash dir:" "$trashdir"
|
|
do_rm "$@"
|
|
}
|
|
|
|
main() {
|
|
# which rm command to use
|
|
rm=''
|
|
|
|
# calculate which rm command to use
|
|
which_rm=''
|
|
if [ -n "${RM:-}" ]; then
|
|
which_rm='custom: '"$RM"
|
|
elif command -v trash > /dev/null; then
|
|
which_rm='trash'
|
|
else
|
|
which_rm='rm'
|
|
fi
|
|
|
|
# print usage information (including which rm command we'll use)
|
|
if [ $# = 0 ]; then
|
|
usage
|
|
exit
|
|
fi
|
|
|
|
# execute rm
|
|
case "$which_rm" in
|
|
rm)
|
|
do_rmnormal "$@";;
|
|
trash)
|
|
do_rmtrash "$@";;
|
|
custom*)
|
|
do_rmcustom "$@";;
|
|
*)
|
|
usage; exit;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|