#!/bin/sh# defrag v0.07 by Con Kolivas <kernel@kolivas.org# Braindead fs-agnostic defrag to rewrite files in order largest to smallest# Run this in the directory you want all the files and subdirectories to be# reordered. It will only affect one partition.# Are you really crazy enough to be using this? It might blow your data# into tiny little useless chunks.## модифицирован hakuionice -c3 -p$$trap 'abort' 1 2 15renice 19 $$ > /dev/nullabort(){ echo -e "\nВыполнение прервано успешно" rm -f tmpfile dirlist exit 1}fail(){ echo -e "\nFailed! Проверьте целостность последнего файла" abort}declare -i filesize=0declare -i numfiles=0declare -i in_chunks=0declare -i out_chunks=0#The maximum size of a file we can easily cache in ramdeclare -i maxsize=$((`awk '/MemTotal/ {print $2}' /proc/meminfo`*1024))(( maxsize-= `awk '/Mapped/ {print $2}' /proc/meminfo` ))(( maxsize/= 2))if [[ -a tmpfile || -a dirlist ]] ; then echo dirlist or tmpfile exists exit 1fi# Sort in the following order:# 1) Depth of directory# 2) Size of directory descending# 3) Filesize descending# I made this crap up. I'ts completely unvalidated.echo -e "Создаю список файлов для обработки... \c"#stupid script to find max directory depthfind -xdev -type d -printf "%d\n" | sort -n | uniq > dirlist#sort directories in descending size ordercat dirlist | while read d;do find -xdev -type d -mindepth $d -maxdepth $d -printf "\"%p\"\n" | \ xargs du -bS --max-depth=0 | \ sort -k 1,1nr -k 2 |\ cut -f2 >> tmpfile if (( $? )) ; then fail fidonerm -f dirlist#sort files in descending size ordercat tmpfile | while read d;do find "$d" -xdev -type f -maxdepth 1 -printf "%s\t%p\n" | \ sort -k 1,1nr | \ cut -f2 >> dirlist if (( $? )) ; then fail fidonerm -f tmpfilenumfiles=`wc -l dirlist | awk '{print $1}'`echo -e "готово, $numfiles файла(-ов) будут дефрагментированы"#copy to temp file, check the file hasn't changed and then overwrite originalcat dirlist | while read i;do (( --numfiles )) if [[ ! -f $i ]]; then continue fi #We could be this paranoid but it would slow it down 1000 times #if [[ `lsof -f -- "$i"` ]]; then # echo -e "\n File $i open! Skipping" # 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ещё $numfiles, (кэширую в озу)...\c" cat "$i" > /dev/null else echo -e "\rещё $numfiles, двигаю $filesize байт...\c" fi in_chunks=`filefrag "$i" | awk '{print $(NF - 2)}'` datestamp=`find "$i" -printf "%s"` if (( in_chunks != 1 )) then cp -a -f "$i" tmpfile out_chunks=`filefrag "tmpfile" | awk '{print $(NF - 2)}'` if (( out_chunks < in_chunks )) then # check the file hasn't been altered since we copied it if [[ `find "$i" -printf "%s"` != $datestamp ]] ; then echo -e " \e[1;41mисходный файл изменился, пропускаю\e[0m" continue fi echo -e " \e[1;36m($in_chunks-->$out_chunks) дефрагментирован $i\e[0m" mv -f tmpfile "$i" else echo -e " \e[3;36m $out_chunks не лучше $in_chunks, пропускаю $i\e[0m" rm tmpfile fi else echo -e " \e[1;34mфайл $i не фрагментирован, пропускаю\e[0m" continue fi if (( $? )) ; then fail fidoneecho -e "\nЗавершено успешно"rm -f dirlist