#!/bin/sh # defrag v0.02 by Con Kolivas /dev/null abort() { echo Aborting rm -f tmpfile dirlist exit 1 } fail() { echo Failed abort } declare -i filesize=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: # Depth of directory ascending # Size descending # Name find -xdev -type f -printf "%d %s %p\n" | sort -k 1,1n -k 2nr -k 3 | awk '{print $3}' > dirlist if (( $? )) ; then fail fi for i in `cat dirlist` do 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 cat $i > /dev/null 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 echo $i changed, not overwriting continue fi mv -f tmpfile $i if (( $? )) ; then fail fi done rm -f dirlist