Skip to content

Instantly share code, notes, and snippets.

@jtraulle
Created March 2, 2014 14:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jtraulle/9307456 to your computer and use it in GitHub Desktop.
Save jtraulle/9307456 to your computer and use it in GitHub Desktop.
Simple Shell script to free-up space on disk based on least recently used files.
#!/bin/bash -u
#Jean Traullé <jean.traulle@etud.u-picardie.fr>
#Under CC0 <http://creativecommons.org/publicdomain/zero/1.0/deed.fr>
#Default size is 20Mo
SIZE=20971520
#Not in dryrun mode by default
DRYRUN=0
#Not recursive by default
RECURSIVE="-maxdepth 1"
#Default void options
RESTRICTTOUSER=
FOLDERS=
USER=
EXTENSION=
CUMULATEDSIZE=0
VERBOSE=0
#Analysing options with getopts and defining variables
while getopts ":s:nRu:e:v" option
do
case $option in
s)
#Option argument need to be a number
PATTERN='^[0-9]+$'
if ! [[ $OPTARG =~ $PATTERN ]]
then
echo "Usage: -$option argument (size in bytes) must be a number"
exit 1
fi
#Option argument need to be greater that 0
if [ $OPTARG -eq 0 ]
then
echo "Usage: -$option argument (size in bytes) must be greater than 0"
exit 1
fi
SIZE=$OPTARG
;;
u)
USER="-user ${OPTARG}"
;;
e)
#Option argument need to be alphanumeric
PATTERN='^[a-z]+$'
if ! [[ $OPTARG =~ $PATTERN ]]
then
echo "Usage: -$option argument (extension) must be alphanumeric"
exit 1
fi
EXTENSION="-name *.${OPTARG}"
;;
v)
VERBOSE=1
;;
R)
RECURSIVE=
;;
n)
DRYRUN=1
;;
:)
echo "-$option option require argument"
exit 1
;;
\?)
echo "Invalid -$OPTARG option"
exit 1
;;
esac
done
#Deleting options and options arguments
shift $((OPTIND-1))
#Script need to have at leat 1 arg
if [ $# -lt 1 ]
then
echo "Usage: pass at least one directory in argument."
exit 1
fi
#Converting all path provided to absolute path
for dir in "$@"
do
if [ -d "$dir" ]
then
FOLDERS="${FOLDERS}$(readlink -f $dir) "
else
echo "mylru: ${dir} is not a directory"
exit 1
fi
done
# Find all files
# - with write right (needed to delete file)
# - with size less that specified -s arg
# - redirect permission and other error messages to blackhole
# - exec option to get :
# - date of last access since epoch
# - size of file in bytes
# - path of file
# - we sort by asc last access date since epoch (after removing = outputed by stat command)
FINDRESULTS=$(find $FOLDERS $RECURSIVE $USER $EXTENSION -type f -writable -size -${SIZE}c 2> /dev/null -exec stat -c="%X:%s:%n" {} \; | cut -d= -f2 | sort -t: -k1n,1)
#If no result, print a message and quit
if [ -z "$FINDRESULTS" ]
then
echo "mylru: No file meet your criteria. Nothing to delete !"
exit 1
fi
#Replacing Internal Field Separator by newline symbol after saving it
#to permit cycling through files paths (which contains spaces).
SAVEIFS=$IFS
IFS=$'\n'
echo ""
#For each founded file, extract epoch, size and path from line
for file in $FINDRESULTS
do
EPOCHFILE=$(echo "$file" | cut -d: -f1)
DATEFILE=$(date -d@"$EPOCHFILE" +%c)
FILESIZE=$(echo "$file" | cut -d: -f2)
FILEPATH=$(echo "$file" | cut -d: -f3-)
#If we do not exeed $SIZE, process for this file
#otherwise, we check the next file in the list.
if [ "$(expr ${CUMULATEDSIZE} + ${FILESIZE})" -lt "${SIZE}" ]
then
CUMULATEDSIZE=$(expr ${CUMULATEDSIZE} + ${FILESIZE})
#If in Dryrun mode, do not delete the file
if [ "${DRYRUN}" -eq 1 ]
then
echo "${FILEPATH}"
else
rm "${FILEPATH}"
echo "rm ${FILEPATH}"
fi
#If user require verbose, print some useful info about the file
if [ "${VERBOSE}" -eq 1 ]
then
echo "${FILESIZE}B, last accessed on ${DATEFILE}"
echo ""
fi
fi
done
#Restoring IFS anterior value
IFS=$SAVEIFS
#Prints total scape freed and quit
echo -e "Total space freed ${CUMULATEDSIZE}B\n"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment