Skip to content

Instantly share code, notes, and snippets.

@x42en
Last active December 21, 2020 18:59
Show Gist options
  • Save x42en/715e83c1d9c6329ba2932e07af43dac8 to your computer and use it in GitHub Desktop.
Save x42en/715e83c1d9c6329ba2932e07af43dac8 to your computer and use it in GitHub Desktop.
A simple bash script to delete files using a specific file date as reference
#!/bin/bash
# Exemple of using getopts from:
# https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash
# saner programming env: these switches turn some bugs into errors
set -o errexit -o pipefail -o noclobber -o nounset
# -allow a command to fail with !’s side effect on errexit
# -use return value from ${PIPESTATUS[0]}, because ! hosed $?
! getopt --test > /dev/null
if [[ ${PIPESTATUS[0]} -ne 4 ]]; then
echo 'I’m sorry, `getopt --test` failed in this environment.'
exit 1
fi
OPTIONS=abdfip:h
LONGOPTS=after,before,debug,force,interactive,path:,help
! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@")
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
# e.g. return value is 1
# then getopt has complained about wrong arguments to stdout
exit 2
fi
# read getopt’s output this way to handle the quoting right:
eval set -- "$PARSED"
a=false b=false d=false f=false i=false h=false directory=.
while true; do
case "$1" in
-a|--after)
a=true
shift
;;
-b|--before)
b=true
shift
;;
-d|--debug)
d=true
shift
;;
-f|--force)
f=true
shift
;;
-i|--interactive)
i=true
shift
;;
-h|--help)
h=true
shift
;;
-p|--path)
directory="$2"
shift 2
;;
--)
shift
break
;;
*)
echo "Programming error"
exit 3
;;
esac
done
if [[ $h = true ]]; then
echo "This script allows you to delete multiple files and directories based on input file date"
echo "Example:"
echo "$0 [--debug] [--force] [--help] [--interactive] [--path /path/where/to/delete/] input_file.txt"
echo ""
echo "Multiple options are available"
echo "-h --help Display this output"
echo "-d --debug Allow debug mode (will NOT delete files found)"
echo "-f --force Remove all output, useful for scripting"
echo "-i --interactive Force interaction with user when suppress"
echo "-p --path Specify a directory where to remove files (default current directory)"
echo "-b --before Remove all files BEFORE reference file date"
echo "-a --after Remove all files AFTER reference file date"
echo "-x --delta Remove all files with a delta of X days from reference file date (use in combination with --before or --after)"
echo ""
exit 0
fi
# handle non-option arguments
if [[ $# -ne 1 ]]; then
echo "$0: A single input file is required."
exit 4
fi
if [[ $d = true ]]; then
echo "force: $f, debug: $d, help: $h, interactive:$i, after:$a, before:$b, in: $1, path: $directory"
fi
# Retrieve date for file or directory
DATE_FOUND=$(ls -lad --time-style=long-iso $1 | awk '{print $6,$7}')
# Search for older files
if [[ $a = true ]]; then
FILTER_COMMAND="find \"${directory%/}\" -maxdepth 1 -newermt \"${DATE_FOUND}:00\" -print 2>/dev/null"
# Search for newer files
elif [[ $b = true ]]; then
FILTER_COMMAND="find \"${directory%/}\" -maxdepth 1 -not -newermt \"${DATE_FOUND}:00\" -print 2>/dev/null"
# Search for files from exact date
else
FILTER_COMMAND="ls -Rald --time-style=long-iso '${directory%/}'/* 2>/dev/null | grep '${DATE_FOUND}' | awk '{print \$8}'"
fi
# On debug display filter command
if [[ $d = true ]]; then
echo $FILTER_COMMAND
fi
# Search for targets
TARGETS=($(eval ${FILTER_COMMAND}))
echo "Found ${#TARGETS[@]}"
# Alert user about deletion if set
if [[ ! $f = true ]]; then
if [[ $a = true ]]; then
echo "I will drop ${#TARGETS[@]} entries in ${directory} AFTER ${DATE_FOUND}"
elif [[ $b = true ]]; then
echo "I will drop ${#TARGETS[@]} entries in ${directory} BEFORE ${DATE_FOUND}"
else
echo "I will drop ${#TARGETS[@]} entries in ${directory} from date ${DATE_FOUND}"
fi
fi
# Recursive list of file based on this date
for target in ${TARGETS[@]}
do
# Avoid dealing with system directories
if [[ $target = '.' || $target = '..' ]]; then
echo "Avoid current dir"
continue
fi
if [[ $d = true ]]; then
echo "- Delete ${target}"
# Never delete files on debug
continue
fi
if [[ $i = true ]]; then
rm -ri ${target}
else
rm -rf ${target}
fi
done
if [[ $d = false ]]; then
echo "All files deleted..."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment