Check free disk space for current partition in bash
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
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
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.
8 Answers 8
for the current directory.
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:
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.
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).
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: 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 🙁
- df command : Report file system disk space usage
- du command : Estimate file space usage
Type df -h or df -k to list free disk space:
du shows how much space one or more files or directories is using:
The -s option summarizes the space a directory is using and -h option provides Human-readable output.
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.
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.
df --output=avail -B 1 "$PWD" |tail -n 1
you get size in bytes this way.
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 $).log MAILCMD=mail EMAILIDS="dude@wheres.mycar" MAILMESSAGE=/tmp/tmp-$(basename $) # ----------------------------------------------------------------------------------------- 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 $ echo -e "\nPotential Files To Delete:" | tee -a $ find $MOUNTP -xdev -type f -size +500M -exec du -sh <> ';' | sort -rh | head -n20 | tee -a $ email_on_failure $ else echo "Currently $(((($FREE-$LIMITSIZE)/1000))) MB of QUOTA available of on $MOUNTP. " fi
How do I programmatically get the free disk space for a directory in Linux
I believe you can calculate ‘free space’ as f_bsize * f_bfree .
NAME statvfs, fstatvfs - get file system statistics SYNOPSIS #include int statvfs(const char *path, struct statvfs *buf); int fstatvfs(int fd, struct statvfs *buf); DESCRIPTION The function statvfs() returns information about a mounted file system. path is the pathname of any file within the mounted file system. buf is a pointer to a statvfs structure defined approximately as follows: struct statvfs < unsigned long f_bsize; /* file system block size */ unsigned long f_frsize; /* fragment size */ fsblkcnt_t f_blocks; /* size of fs in f_frsize units */ fsblkcnt_t f_bfree; /* # free blocks */ fsblkcnt_t f_bavail; /* # free blocks for unprivileged users */ fsfilcnt_t f_files; /* # inodes */ fsfilcnt_t f_ffree; /* # free inodes */ fsfilcnt_t f_favail; /* # free inodes for unprivileged users */ unsigned long f_fsid; /* file system ID */ unsigned long f_flag; /* mount flags */ unsigned long f_namemax; /* maximum filename length */ >;
statvfs does not seem to work for vfat mounted drives. I tried it with a FAT 32 partition and its gives 0 for available blocks. Is there a way to work it out?
@ShadmanAnwer unfortunately the man page says: It is unspecified whether all members of the returned struct have meaningful values on all file systems. So perhaps FAT32 is not supported in this case.
I get huge difference between f_bfree and f_bavail, that’s really weird, around 40%. But ‘df’ as @speed488 says is consistent with f_bavail.
The difference between f_bfree and f_bavail is due to blocks reserved for the super user (ext2/3/4 file systems). This defaults to 5% of the disk. It can be altered using tune2fs with options -r
You can use boost::filesystem:
struct space_info // returned by space function < uintmax_t capacity; uintmax_t free; uintmax_t available; // free space available to a non-privileged process >; space_info space(const path& p); space_info space(const path& p, system::error_code& ec);
#include using namespace boost::filesystem; space_info si = space("."); cout
Returns: An object of type space_info. The value of the space_info object is determined as if by using POSIX statvfs() to obtain a POSIX struct statvfs, and then multiplying its f_blocks, f_bfree, and f_bavail members by its f_frsize member, and assigning the results to the capacity, free, and available members respectively. Any members for which the value cannot be determined shall be set to -1.
Get the free space available in current directory in Bash
The output can be made a bit easier to parse by using the -P option which will ensure that:
- The information about each file system is always printed on exactly one line; a mount device is never put on a line by itself. This means that if the mount device name is more than 20 characters long (e.g., for some network mounts), the columns are misaligned.
This makes it much easier to get just the free space available:
( -h uses megabytes, gigabytes and so on. If your system doesn't have it, use -k for kilobytes only.)
If we pass df a path, it is only going to return 2 rows: a header row and then the data about the file system that contains the path. We can use tail to grab just the second row. We know that the space available is in the 4th column, so we grab that with awk . This all could be done with awk :
You can optimize your command by using the environment variable $PWD instead of using command substitution and removing the need for tail: df -Ph $PWD | awk 'NR==2
@SiegeX: I agree doing it all in awk is better. I included the longer command because I wanted to have an example of how one can construct a chain of simple commands to do something more complicated. I've updated the answer to include your improvement.
-P is standard (the P is for POSIX). But -h is a GNU extension (also existing on some other systems, but e.g. on OpenBSD it's incompatible with -P ).
"You can optimize your command". Not really. Running both pipes 10'000 times (as in time < I=0; while [ $I -lt 10000 ]; do df -Ph . | awk 'NR==2
How about doing df -h . . This will give you the available free space of the partition your current working directory is in.
/usr/local/nagios/libexec # df -h . Filesystem Size Used Avail Use% Mounted on /dev/mapper/vg00-lvol1 9.9G 6.1G 3.4G 65% /
df --output=avail -B 1 "$PWD" | tail -n 1
df --output=avail -h "$PWD" | tail -n 1
df --output=avail -B 1 "$PWD" |tail -n 1 | numfmt --to="iec"
df --output=avail -B 1 "$PWD" |tail -n 1 | numfmt --grouping
You can simply do it like this:
Command Interpretation:
df : (disk free) is a standard Unix command used to display the amount of available disk space for file systems on which the invoking user has appropriate read access.
-h : to show the output in a human-readable format i.e. megabytes, gigabytes, and so on.
$PWD : Invoke the command in the current directory.
| : pass the output of the leftmost command to the rightmost one.
awk : is a utility that enables a programmer to scan each input file for lines that match any of a set of patterns specified literally in prog or in one or more files specified as -f file.
'NR==2 : Get the second row that contains the space numeric value, not the header -NR==1-.
'': Get the 4th column which contains the available space.