212 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env bash
 | 
						|
 | 
						|
# Cleanup
 | 
						|
set -e
 | 
						|
trap 'exit 1' SIGINT
 | 
						|
 | 
						|
# Constants
 | 
						|
VERSION='2.0.0'
 | 
						|
RED=$'\e[1;31m'
 | 
						|
GREEN=$'\e[1;32m'
 | 
						|
BLUE=$'\e[1;34m'
 | 
						|
YELLOW=$'\e[1;33m'
 | 
						|
WHITE_BOLD=$'\e[1;37m'
 | 
						|
RESET=$'\e[0;0m'
 | 
						|
 | 
						|
fd_opts=(--hidden --threads "$(nproc)")
 | 
						|
rm_opts=(--verbose)
 | 
						|
declare -a typeopts
 | 
						|
 | 
						|
# Helper functions
 | 
						|
function help() {
 | 
						|
    cat << HELPMESSAGE
 | 
						|
$(basename "$0") $VERSION
 | 
						|
 | 
						|
Usage: $(basename "$0") [-h] [-d] [-e] [-E ext] [-f] [-F] [-I] [-i] [-l] patterns [patterns ...]
 | 
						|
 | 
						|
positional arguments:
 | 
						|
  patterns              file matching patterns
 | 
						|
 | 
						|
options:
 | 
						|
  -h, --help            show this help message and exit
 | 
						|
  -d, --directories-only
 | 
						|
                        filter results to directories
 | 
						|
  -e, --empty-only      filter results to empty files and directories
 | 
						|
  -E ext, --extension ext
 | 
						|
                        file extension
 | 
						|
  -f, --files-only      filter results to files
 | 
						|
  -F, --force-directory-delete
 | 
						|
                        do not ignore non-empty directories, delete anyways
 | 
						|
  -I, --no-ignore-vcs   do not ignore .gitignore
 | 
						|
  -i, --no-ignore       do not ignore .gitignore and .fdignore
 | 
						|
  -l, --links-only      filter results to symlinks
 | 
						|
HELPMESSAGE
 | 
						|
}
 | 
						|
 | 
						|
# $1 is the output string, $2 is the color
 | 
						|
function color_output() {
 | 
						|
    case "$2" in
 | 
						|
        'red')
 | 
						|
            printf "$RED%s\n" "$1"
 | 
						|
            ;;
 | 
						|
        'green')
 | 
						|
            printf "$GREEN%s\n" "$1"
 | 
						|
            ;;
 | 
						|
        'blue')
 | 
						|
            printf "$BLUE%s\n" "$1"
 | 
						|
            ;;
 | 
						|
        'yellow')
 | 
						|
            printf "$YELLOW%s\n" "$1"
 | 
						|
            ;;
 | 
						|
        'white')
 | 
						|
            printf "$WHITE_BOLD%s\n" "$1"
 | 
						|
            ;;
 | 
						|
        'reset')
 | 
						|
            printf "$RESET%s\n" "$1"
 | 
						|
            ;;
 | 
						|
    esac
 | 
						|
}
 | 
						|
 | 
						|
# Color files blue and directories green
 | 
						|
function color_path() {
 | 
						|
    if [[ -f "$1" ]]; then
 | 
						|
        color_output "$1" 'blue'
 | 
						|
    elif [[ -d "$1" ]]; then
 | 
						|
        color_output "$1" 'green'
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# Delete path using correct command
 | 
						|
# Parameters:
 | 
						|
#   - $1: path
 | 
						|
#   - $2: force delete boolean flag
 | 
						|
function delete() {
 | 
						|
    exit 1
 | 
						|
}
 | 
						|
 | 
						|
while true; do
 | 
						|
    case "${1}" in
 | 
						|
        '-d' | '--directories-only')
 | 
						|
            typeopts+=(--type directory)
 | 
						|
            shift
 | 
						|
            continue
 | 
						|
            ;;
 | 
						|
        '-e' | '--empty-only')
 | 
						|
            typeopts+=(--type empty)
 | 
						|
            shift
 | 
						|
            continue
 | 
						|
            ;;
 | 
						|
        '-E' | '--extension')
 | 
						|
            EXT="${2}"
 | 
						|
            case "${EXT}" in
 | 
						|
                "")
 | 
						|
                    exit 1
 | 
						|
                    ;;
 | 
						|
                -*)
 | 
						|
                    exit 1
 | 
						|
                    ;;
 | 
						|
            esac
 | 
						|
            fd_opts+=(--extension "$EXT")
 | 
						|
            shift 2
 | 
						|
            continue
 | 
						|
            ;;
 | 
						|
        --extension=*)
 | 
						|
            EXT="${1#*=}"
 | 
						|
            case "${EXT}" in
 | 
						|
                "")
 | 
						|
                    exit 1
 | 
						|
                    ;;
 | 
						|
                -*)
 | 
						|
                    exit 1
 | 
						|
                    ;;
 | 
						|
            esac
 | 
						|
            fd_opts+=(--extension "$EXT")
 | 
						|
            shift
 | 
						|
            continue
 | 
						|
            ;;
 | 
						|
        '-f' | '--files-only')
 | 
						|
            typeopts+=(--type file)
 | 
						|
            shift
 | 
						|
            continue
 | 
						|
            ;;
 | 
						|
        '-F' | '--force-directory-delete')
 | 
						|
            rm_opts+=(--recursive --force)
 | 
						|
            shift
 | 
						|
            continue
 | 
						|
            ;;
 | 
						|
        '-i' | '--no-ignore-vcs')
 | 
						|
            fd_opts+=('--no-ignore-vcs')
 | 
						|
            shift
 | 
						|
            continue
 | 
						|
            ;;
 | 
						|
        '-I' | '--no-ignore')
 | 
						|
            fd_opts+=('--no-ignore')
 | 
						|
            shift
 | 
						|
            continue
 | 
						|
            ;;
 | 
						|
        '-l' | '--links-only')
 | 
						|
            typeopts+=(--type symlink)
 | 
						|
            shift
 | 
						|
            continue
 | 
						|
            ;;
 | 
						|
        '-h' | '--help')
 | 
						|
            help
 | 
						|
            exit
 | 
						|
            ;;
 | 
						|
        --)
 | 
						|
            shift
 | 
						|
            break
 | 
						|
            ;;
 | 
						|
        -*)
 | 
						|
            printf '%s\n' "Unknown option: ${1}" >&2
 | 
						|
            exit 1
 | 
						|
            ;;
 | 
						|
        *)
 | 
						|
            break
 | 
						|
            ;;
 | 
						|
    esac
 | 
						|
done
 | 
						|
 | 
						|
# Interpret options
 | 
						|
# If nothing was entered
 | 
						|
if [[ -z "$*" ]]; then
 | 
						|
    help
 | 
						|
    exit 1
 | 
						|
fi
 | 
						|
 | 
						|
declare -a files pattern_results
 | 
						|
 | 
						|
for pattern in "$@"; do
 | 
						|
    readarray -d $'\n' -t pattern_results <<< "$(fd "${fd_opts[@]}" "${typeopts[@]}" "$pattern")"
 | 
						|
    files+=("${pattern_results[@]}")
 | 
						|
done
 | 
						|
 | 
						|
# If nothing was found
 | 
						|
if [[ -z "${files[*]}" ]]; then
 | 
						|
    color_output 'No files found, exiting' 'yellow'
 | 
						|
    exit 1
 | 
						|
fi
 | 
						|
 | 
						|
# Sort list of paths before printing
 | 
						|
readarray -t paths < <(printf '%s\n' "${files[@]}" | sort --unique)
 | 
						|
 | 
						|
# Print list of files found matching criteria
 | 
						|
i=1
 | 
						|
for p in "${paths[@]}"; do
 | 
						|
    printf '%s. %s\n' "$(color_output $i 'white')" "$(color_path "$p")"
 | 
						|
    i=$((i + 1))
 | 
						|
done
 | 
						|
 | 
						|
# Padding between files and prompt
 | 
						|
color_output '' reset
 | 
						|
 | 
						|
read -r -n 1 -p 'Would you like to delete these files? [y/N]: ' user_response
 | 
						|
# Padding between prompt and output
 | 
						|
echo ''
 | 
						|
 | 
						|
if [[ "$user_response" =~ (y|Y) ]]; then
 | 
						|
    for p in "${paths[@]}"; do
 | 
						|
        rm "${rm_opts[@]}" -- "$p" || printf '%s %s\n' "$(color_output "Unable to remove path:" 'red')" "$(color_path "$p")"
 | 
						|
    done
 | 
						|
fi
 |