#!/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 "$@"