150

I am writing an installer in bash. The user will go to the target directory and runs the install script, so the first action should be to check that there is enough space. I know that df will report all file systems, but I was wondering if there was a way to get the free space just for the partition that the target directory is on.

Edit - the answer I came up with

df $PWD | awk '/[0-9]%/{print $(NF-2)}'

Slightly odd because df seems to format its output to fit the terminal, so with a long mount point name the output is shifted down a line

mgoldwasser
  • 14,558
  • 15
  • 79
  • 103
Greg Reynolds
  • 9,736
  • 13
  • 49
  • 60
  • 4
    Use the `-P` flag to `df`, you'll get it all on one line. – Mat Nov 13 '11 at 09:19
  • 6
    related `du -hs .` to see the disk space in use for current directory. – here Jun 11 '13 at 22:45
  • As @Mat said, you will want to use -P if you go with your solution. In the past I've encountered oddly formatted or long named partitions that caused a script to fail because the -P flag was missing. – SuperTetelman Mar 14 '17 at 01:36

8 Answers8

243

Yes:

df -k .

for the current directory.

df -k /some/dir

if you want to check a specific directory.

You might also want to check out the stat(1) command if your system has it. You can specify output formats to make it easier for your script to parse. Here's a little example:

$ echo $(($(stat -f --format="%a*%S" .)))
Mat
  • 202,337
  • 40
  • 393
  • 406
  • Thanks for that! stat looks a bit mind-blowing to me. Reading the man page suggests I don't want -k on my version of df, but putting the path in did help. – Greg Reynolds Nov 13 '11 at 09:14
  • Ahh - now I see why you use -k, makes the calculations easier! – Greg Reynolds Nov 13 '11 at 09:19
  • 1
    The thing is a lot of systems will default to 512 byte blocks if you don't specify `-k`. (coreutils df defaults to 1k blocks, so you're pretty safe on Linux though - but if you have coreutils, you have `stat`, and that's even safer - no parsing required). – Mat Nov 13 '11 at 09:21
  • 2
    In my Red-Hat something, the format string should be `%a*%s` instead of `%a*%S`. I'm not sure if this is a difference or a typo. – RnMss Jun 27 '13 at 08:00
  • @RnMss: It's _supposed_ to be `%S` (capital) according to the man page on RedHat. Can't find a filesystem where `%s != %S` on the few RedHats I have access too though, so can't check :-( – Mat Jun 27 '13 at 09:00
  • echo $(($(stat -f --format="%a*%S" /folder)/10**6)) to get it in MB – Mike Q Jun 03 '14 at 16:08
  • Does not work on Mac OS: You get an error like `bash: --format=1471613078*: attempted assignment to non-variable (error token is "=1471613078*")` – sorin Aug 19 '16 at 13:28
  • @sorin: question is tagged Linux. That error is a bit strange though, are you sure you typed it in correctly? I don't know what version of `stat` MacOS has, if it's not from GNU coreutils, chances are it won't work. – Mat Aug 19 '16 at 14:36
  • `k` and `h` at the same time doesn't make much sense, @Loïc. Just use `h` for human readable. – Mat Sep 11 '16 at 16:47
62
  1. df command : Report file system disk space usage
  2. du command : Estimate file space usage

Type df -h or df -k to list free disk space:

 $ df -h

OR

 $ df -k

du shows how much space one or more files or directories is using:

 $ du -sh

The -s option summarizes the space a directory is using and -h option provides Human-readable output.

Eric Leung
  • 2,354
  • 12
  • 25
Girish
  • 11,907
  • 3
  • 34
  • 51
33

I think this should be a comment or an edit to ThinkingMedia's answer on this very question (Check free disk space for current partition in bash), but I am not allowed to comment (not enough rep) and my edit has been rejected (reason: "this should be a comment or an answer"). So please, powers of the SO universe, don't damn me for repeating and fixing someone else's "answer". But someone on the internet was wrong!™ and they wouldn't let me fix it.

The code

  df --output=avail -h "$PWD" | sed '1d;s/[^0-9]//g'

has a substantial flaw: Yes, it will output 50G free as 50 -- but it will also output 5.0M free as 50 or 3.4G free as 34 or 15K free as 15.

To create a script with the purpose of checking for a certain amount of free disk space you have to know the unit you're checking against. Remove it (as sed does in the example above) the numbers don't make sense anymore.

If you actually want it to work, you will have to do something like:

FREE=`df -k --output=avail "$PWD" | tail -n1`   # df -k not df -h
if [[ $FREE -lt 10485760 ]]; then               # 10G = 10*1024*1024k
     # less than 10GBs free!
fi;

Also for an installer to df -k $INSTALL_TARGET_DIRECTORY might make more sense than df -k "$PWD". Finally, please note that the --output flag is not available in every version of df / linux.

Community
  • 1
  • 1
trs
  • 1,038
  • 9
  • 19
6
df --output=avail -B 1 "$PWD" |tail -n 1

you get size in bytes this way.

xerostomus
  • 466
  • 4
  • 11
5

A complete example for someone who may want to use this to monitor a mount point on a server. This example will check if /var/spool is under 5G and email the person :

  #!/bin/bash
  # -----------------------------------------------------------------------------------------
  # SUMMARY: Check if MOUNT is under certain quota, mail us if this is the case
  # DETAILS: If under 5G we have it alert us via email. blah blah  
  # -----------------------------------------------------------------------------------------
  # CRON: 0 0,4,8,12,16 * * * /var/www/httpd-config/server_scripts/clear_root_spool_log.bash

  MOUNTP=/var/spool  # mount drive to check
  LIMITSIZE=5485760 # 5G = 10*1024*1024k   # limit size in GB   (FLOOR QUOTA)
  FREE=$(df -k --output=avail "$MOUNTP" | tail -n1) # df -k not df -h
  LOG=/tmp/log-$(basename ${0}).log
  MAILCMD=mail
  EMAILIDS="dude@wheres.mycar"
  MAILMESSAGE=/tmp/tmp-$(basename ${0})

  # -----------------------------------------------------------------------------------------

  function email_on_failure(){

          sMess="$1"
          echo "" >$MAILMESSAGE
          echo "Hostname: $(hostname)" >>$MAILMESSAGE
          echo "Date & Time: $(date)" >>$MAILMESSAGE

          # Email letter formation here:
          echo -e "\n[ $(date +%Y%m%d_%H%M%S%Z) ] Current Status:\n\n" >>$MAILMESSAGE
          cat $sMess >>$MAILMESSAGE

          echo "" >>$MAILMESSAGE
          echo "*** This email generated by $(basename $0) shell script ***" >>$MAILMESSAGE
          echo "*** Please don't reply this email, this is just notification email ***" >>$MAILMESSAGE

          # sending email (need to have an email client set up or sendmail)
          $MAILCMD -s "Urgent MAIL Alert For $(hostname) AWS Server" "$EMAILIDS" < $MAILMESSAGE

          [[ -f $MAILMESSAGE ]] && rm -f $MAILMESSAGE

  }

  # -----------------------------------------------------------------------------------------

  if [[ $FREE -lt $LIMITSIZE ]]; then
          echo "Writing to $LOG"
          echo "MAIL ERROR: Less than $((($FREE/1000))) MB free (QUOTA) on $MOUNTP!" | tee ${LOG}
          echo -e "\nPotential Files To Delete:" | tee -a ${LOG}
          find $MOUNTP -xdev -type f -size +500M -exec du -sh {} ';' | sort -rh | head -n20 | tee -a ${LOG}
          email_on_failure ${LOG}
  else
          echo "Currently $(((($FREE-$LIMITSIZE)/1000))) MB of QUOTA available of on $MOUNTP. "
  fi
Mike Q
  • 6,716
  • 5
  • 55
  • 62
5

This is one of those questions where everyone has their favorite approach, but since I have returned to this page a few times over the years I will share one of my solutions (inspired by others here).

DISK_SIZE_TOTAL=$(df -kh . | tail -n1 | awk '{print $2}')
DISK_SIZE_FREE=$(df -kh . | tail -n1 | awk '{print $4}')
DISK_PERCENT_USED=$(df -kh . | tail -n1 | awk '{print $5}')

Since it's just using df and pulling row/columns via awk it should be fairly portable.

Then you can use this in a script, like maybe:

"${DISK_SIZE_FREE}" available out of "${DISK_SIZE_TOTAL}" total ("${DISK_PERCENT_USED}" used).

Example: https://github.com/littlebizzy/slickstack/blob/master/bash/ss-install.txt

The final result looks like this:

10GB available out of 20GB total (50% used).

Jesse Nickles
  • 1,435
  • 1
  • 17
  • 25
1

To know the usage of the specific directory in GB's or TB's in Linux the command is:

df -h /dir/inner_dir/

or:

df -sh /dir/inner_dir/

and to know the usage of the specific directory in bits in Linux the command is:

df -k /dir/inner_dir/
AntonioK
  • 440
  • 6
  • 20
0

Type in the command shell:

 df -h 

or

df -m

or

df -k

It will show the list of free disk spaces for each mount point.

You can show/view single column also.

Type:

df -m |awk '{print $3}'

Note: Here 3 is the column number. You can choose which column you need.

Masud Sarker
  • 159
  • 2
  • 13
  • Yes it's a great trick (pulling columns)... here is a related link if anyone wants to learn more about this in detail: https://stackoverflow.com/questions/16136943/how-to-get-the-second-column-from-command-output – Jesse Nickles Mar 30 '22 at 09:24