├── README.md └── btrfs-size.sh /README.md: -------------------------------------------------------------------------------- 1 | # BTRFS-Size 2 | A script that will print out a list of BTRFS subvolumes along with their size in megabytes and their name 3 | 4 | You will need to enable quotas first. Run this command as root: `btrfs quota enable /` 5 | 6 | For more information check out this [blog entry](https://poisonpacket.wordpress.com/2015/05/26/btrfs-snapshot-size-disk-usage/). 7 | 8 | To invoke just run: 9 | ```bash 10 | ./btrfs-size.sh 11 | ``` 12 | 13 | To run on a directory outside root run: 14 | ```bash 15 | ./btrfs-size.sh /path 16 | ``` 17 | 18 | Example output: 19 | ``` 20 | Snapshot / Subvolume Total Exclusive Data ID 21 | ============================================================================================================== 22 | @ 16.00KB 256 23 | @/home 346.98MB 257 24 | @/boot/grub2/x86_64-efi 4.18MB 258 25 | @/boot/grub2/i386-pc 16.00KB 259 26 | @/.snapshots 640.00KB 260 27 | @/.snapshots/1/snapshot 82.39GB 261 28 | @/.snapshots/391/snapshot 81.52GB 651 29 | @/.snapshots/392/snapshot 81.54GB 652 30 | @/.snapshots/393/snapshot 81.65GB 653 31 | @/.snapshots/394/snapshot 81.59GB 654 32 | @/.snapshots/397/snapshot 81.85GB 657 33 | @/.snapshots/398/snapshot 82.22GB 658 34 | @/.snapshots/399/snapshot 82.24GB 659 35 | @/.snapshots/400/snapshot 82.05GB 660 36 | @/.snapshots/405/snapshot 82.04GB 665 37 | @/.snapshots/406/snapshot 82.32GB 666 38 | @/.snapshots/407/snapshot 82.31GB 667 39 | @/.snapshots/408/snapshot 82.31GB 668 40 | @/.snapshots/409/snapshot 82.34GB 669 41 | @/.snapshots/410/snapshot 82.29GB 670 42 | @/.snapshots/411/snapshot 82.32GB 671 43 | @/.snapshots/412/snapshot 82.51GB 672 44 | @/.snapshots/413/snapshot 82.52GB 673 45 | @/.snapshots/414/snapshot 82.38GB 674 46 | ============================================================================================================== 47 | Exclusive Total: 14.89GB 48 | ``` 49 | -------------------------------------------------------------------------------- /btrfs-size.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #Author Kyle Agronick 3 | #Usage: Invoke this script to get the size of your subvolumes and snapshots 4 | #Make sure to run "sudo btrfs quota enable /" first 5 | 6 | 7 | LOCATION='/' 8 | if [ $1 ]; then 9 | LOCATION=$1 10 | fi 11 | 12 | OUTPUT="" 13 | 14 | COL1=`sudo btrfs subvolume list "$LOCATION"` 15 | 16 | if [ $? -ne 0 ]; then 17 | echo "Failed to the volume data! BTRFS volume is required on the target location!" 18 | exit 1 19 | fi 20 | 21 | COL1=$(echo "$COL1" | cut -d ' ' -f 2,9) # Only taking the ID and the Snapshot name 22 | 23 | COL2=`sudo btrfs qgroup show "$LOCATION" --raw 2>&1` 24 | 25 | if [ $? -ne 0 ]; then 26 | echo "Failed to get size on the target location! Is quota enabled?" 27 | exit 1 28 | fi 29 | 30 | CONTINUE=false 31 | if [[ $COL2 == *"unrecognized option"* ]]; then 32 | COL2=`sudo btrfs qgroup show "$LOCATION" ` 33 | fi 34 | 35 | COL2=$(echo "$COL2" | cut -c 2-) 36 | 37 | 38 | function convert() 39 | { 40 | OUT=`echo "$i" | awk '{ sum=$1 ; hum[1024^4]="TB";hum[1024^3]="GB";hum[1024^2]="MB";hum[1024]="KB"; for (x=1024^4; x>=1024; x/=1024){ if (sum>=x) { printf "%.2f%s\n",sum/x,hum[x];break } }}'` 41 | OUTPUT=$(printf "%-9s" $OUT) 42 | echo "$OUTPUT" 43 | } 44 | 45 | i=0 46 | ECL_TOTAL=0 47 | INDEX=0 48 | LC_ALL=C 49 | for i in $COL2; do 50 | if [[ $i == *"groupid"* ]] || [[ $i == *"----"* ]]; then 51 | continue; 52 | fi 53 | if [[ ! $i =~ ^[A-Za-z-]+$ ]]; then 54 | if [[ "$i" == *\/* ]]; then 55 | INDEX=0 56 | ROWID=$(echo "$i" | cut -c 2-) 57 | OUTPUT+=" 58 | $ROWID " 59 | else 60 | ((INDEX++)) 61 | if [ -z `echo $i | tr -d "[:alpha:]"` ]; then 62 | echo $i" letters\n" 63 | OUTPUT="$OUTPUT"$(printf "%-9s" $i) 64 | else 65 | if [ $INDEX -eq 2 ]; then 66 | ECL_TOTAL=$(($i + $ECL_TOTAL)) 67 | fi 68 | OUTPUT="$OUTPUT$(convert $i)" 69 | fi 70 | fi 71 | fi 72 | done 73 | 74 | 75 | # Determine terminal width 76 | if hash tput 2>/dev/null; then 77 | COLCOUNT=`tput cols` 78 | elif hash stty 2>/dev/null; then 79 | COLCOUNT=`stty size | cut -d' ' -f2` 80 | else 81 | COLCOUNT=80 # Default 82 | fi 83 | 84 | declare -a COLUMNWIDHTS=(-$(($COLCOUNT-30)) 20 6) 85 | 86 | function printRow 87 | { 88 | DATA=("$@") 89 | 90 | # The offset is calculated to help aligning the next column properly, 91 | # if the preveious one was too long 92 | local offset=0 93 | for ((i=0;i < $#;i++)) 94 | { 95 | local modifier="" 96 | local width=${COLUMNWIDHTS[$i]} 97 | if [ $width -lt 0 ]; then 98 | width=$((0-$width)) # Gettings abs value 99 | modifier="-." # Left-padded and truncating if too long 100 | fi 101 | local pattern="%$modifier*s" 102 | local column # The current column with padding 103 | printf -v column $pattern $(($width + $offset)) "${DATA[$i]}" 104 | printf "$column" 105 | offset=$(($offset + $width - ${#column})) 106 | } 107 | printf "\n" 108 | } 109 | 110 | function printHorizontalLine 111 | { 112 | printf '%*s\n' $COLCOUNT '' | tr ' ' '=' 113 | } 114 | 115 | # Header start 116 | printHorizontalLine 117 | printRow "Snapshot / Subvolume" "Total Exclusive Data" "ID" 118 | printHorizontalLine 119 | # Header end 120 | 121 | IFS=$'\n' 122 | 123 | # Table body start 124 | for item in $COL1; do 125 | ID=$(echo $item | cut -d' ' -f1) 126 | name=$(echo $item | cut -d' ' -f2) 127 | for item2 in $OUTPUT; do 128 | ID2=$(echo $item2 | grep -o '^[0-9.]\+' ) 129 | if [ "$ID" = "$ID2" ]; then 130 | eval ROWDATA=($(echo $name ${item2[@]} | awk -F' ' '{print $1, $3, $2}')) 131 | printRow "${ROWDATA[@]}" 132 | break; 133 | fi 134 | done 135 | done 136 | # Table body end 137 | 138 | if [ $ECL_TOTAL -gt "1" ]; then 139 | printHorizontalLine 140 | i=$ECL_TOTAL 141 | printf "%-64s" " " 142 | printf "Exclusive Total: $(convert $i) \n" 143 | fi 144 | --------------------------------------------------------------------------------