Last active
December 21, 2020 18:59
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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