Defragging files in btrfs - Oneliner
April 10, 2020 —
Jesse Harris
Sometimes, small databasey files get a bit fragmented over time on a COW filesystem. This touch of shell is a goodone to clean them up every now and then.
find -size +1024k -size 50000k -type f -exec filefrag {} \; |
awk '{a=NF-2; if ($a>50) {sub(/:.*/,"");print$0}}'|
xargs -I{} btrfs fi defrag "{}"
Pulling it apart
find
-size +1024k -size -50000k
# this tells find to only show files between 1mb and 50mb
-type f
# only find files
-exec filefrag {} ;\
# run filefrag on each file, which shows a count of fragments on each
# file
awk
a=NF-2
# files may have spaces in the name and filefrag lists the filename
# first, instead lets look the second from the last field number (NF =
Number of fields in a given line)
if ($a>50)
# only work on files with frags over 50
sub(/:.*/,"")
# from $0 (the whole line), substitue anything past : with nothing,
# making $0 reference the filename, spaces and all
xargs
-I{}
# in the following command substitue {} with the incoming stdin (ie the
# filename
btrfs fi defrag "{}"
# defrag the file.