From 51616211d89b218fd98b88790a0beedd36a86615 Mon Sep 17 00:00:00 2001 From: PowerUser64 Date: Thu, 13 Mar 2025 01:13:28 -0700 Subject: [PATCH] shell: add rm-prefer-trash script --- .config/shell/bin/rm-prefer-trash | 170 ++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100755 .config/shell/bin/rm-prefer-trash diff --git a/.config/shell/bin/rm-prefer-trash b/.config/shell/bin/rm-prefer-trash new file mode 100755 index 0000000..6287751 --- /dev/null +++ b/.config/shell/bin/rm-prefer-trash @@ -0,0 +1,170 @@ +#!/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 "$@"