About | Links | Scripts
Sharing linux/windows scripts and tips

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


    -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


    # 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

    # from $0 (the whole line), substitue anything past : with nothing,
    # making $0 reference the filename, spaces and all


    # in the following command substitue {} with the incoming stdin (ie the
    # filename

    btrfs fi defrag "{}"
    # defrag the file.

Tags: btrfs, bash, bash-tips, awk