#!/bin/sh # defrag v0.04 by Con Kolivas /dev/null abort() { echo -e "\nAborting" rm -f tmpfile dirlist exit 1 } fail() { echo -e "\nFailed" abort } declare -i filesize=0 declare -i numfiles=0 #The maximum size of a file we can easily cache in ram declare -i maxsize=`awk '/MemTotal/ {print $2}' /proc/meminfo` (( maxsize-= `awk '/Mapped/ {print $2}' /proc/meminfo` )) (( maxsize/= 2)) if [[ -a tmpfile || -a dirlist ]] ; then echo dirlist or tmpfile exists exit 1 fi # Sort in the following order: # 1) Depth of directory # 2) Directory name # 3) Size descending # 4) FileName echo "Creating list of files to defrag..." find -xdev -type f -printf "%d\t%h\t%s\t%p\n" | \ sort -t \t -k 1,1n -k 2,2 -k 3,3nr -k 4 | \ awk -F "\t" '{print $4}' > dirlist if (( $? )) ; then fail fi numfiles=`wc -l dirlist | awk '{print $1}'` echo -e "$numfiles files to defrag \n" cat dirlist | while read i; do (( --numfiles )) if [[ ! -f $i ]]; then continue fi filesize=`find "$i" -printf "%s"` # read the file first to cache it in ram if possible if (( filesize < maxsize )) then echo -e "\r Files left to defrag: $numfiles \c" cat "$i" > /dev/null else echo -e "\r Defragging large file sized $filesize ... \c" fi datestamp=`find "$i" -printf "%s"` cp -a -f "$i" tmpfile if (( $? )) ; then fail fi # check the file hasn't been altered since we copied it if [[ `find "$i" -printf "%s"` != $datestamp ]] ; then continue fi mv -f tmpfile "$i" if (( $? )) ; then fail fi done echo -e "\n" rm -f dirlist