Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How can I get the size of a file in a bash script?

How do I assign this to a bash variable so I can use it later?

share|improve this question

migrated from stackoverflow.com Jul 14 '11 at 0:59

This question came from our site for professional and enthusiast programmers.

up vote 70 down vote accepted

Your best bet:

stat --printf="%s" file.any

NOTE: see @chbrown answer below how to use stat in terminal on Mac OS X or

FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."
share|improve this answer
you know I'm just a newbie and I'm eager to learn... they say there's not such thing as dumb question; I honestly didn't know about stat. Thank you for your help. Appreciated. – haunted85 Jul 13 '11 at 16:47
@haunted85 stat is the most straightforward way, assuming you're using Linux or Cygwin (stat isn't standard). wc -c as suggested by Eugéne is portable. – Gilles Jul 14 '11 at 10:02
file_size_kb=`du -k "$filename" | cut -f1`

The problem with using stat is that it is a GNU (Linux) extension. du -k and cut -f1 are specified by POSIX and are therefore portable to any Unix system.

Solaris, for example, ships with bash but not with stat. So this is not entirely hypothetical.

ls has a similar problem in that the exact format of the output is not specified, so parsing its output cannot be done portably. du -h is also a GNU extension.

Stick to portable constructs where possible, and you will make somebody's life easier in the future. Maybe your own.

share|improve this answer
du doesn't give the size of the file, it gives an indication of how much space the file uses, which is subtly different (usually the size reported by du is the size of the file rounded up to the nearest number of blocks, where a block is typically 512B or 1kB or 4kB). – Gilles Jul 14 '11 at 10:00
@Gilles, sparse files (i.e., ones with holes in them) report less than the length. – vonbrand Jan 9 at 22:03

You could also use the "word count" command (wc):

wc -c $FILENAME| awk '{print $1}'

The problem with wc is that it'll add the filename and indent the file. If you would like to avoid chaining a full interpreted language just to get a file then:

wc -c $FILENAME| sed 's/ *\([^ ]*\)\ *.*/\1/'

should also work just fine...

or you could try:

wc -c < $FILENAME

which, with an assignment using back-quote semantics in Bourne Shell or the $() KSH/Bash command expansion as mentioned by Gilles below allows you to easily use the value you were seeking.

share|improve this answer
wc -c <"$FILENAME" gives the size with no other cruft, thus size=$(wc -c <"$FILENAME"). – Gilles Jul 14 '11 at 9:58
Thanks Gilles, added and clarified. – Eugéne Jun 12 '13 at 17:40
I've had problems with using < and wc. Correct file sizes are only guaranteed when using a filename argument. – Qix Jan 30 at 10:33
Just one more point: I just tested it and wc -c < file seems to be very fast, at least on OS X. I'm guessing that wc has the brains to try to stat the file if only -c is specified. – Edward Falk Apr 4 at 16:29

BSD's (Mac OS X's) stat has a different format argument flag, and different field specifiers. From man stat(1):

  • -f format: Display information using the specified format. See the FORMATS section for a description of valid formats.
  • ... the FORMATS section ...
  • z: The size of file in bytes.

So all together now:

stat -f%z myfile1.txt
share|improve this answer

This script combines many ways to calculate the file size:

  du --apparent-size --block-size=1 "$file" 2>/dev/null ||
  gdu --apparent-size --block-size=1 "$file" 2>/dev/null ||
  find "$file" -printf "%s" 2>/dev/null ||
  gfind "$file" -printf "%s" 2>/dev/null ||
  stat --printf="%s" "$file" 2>/dev/null ||
  stat -f%z "$file" 2>/dev/null ||
  wc -c <"$file" 2>/dev/null
) | awk '{print $1}'

The script works on many Unix systems including Linux, BSD, OSX, Solaris, SunOS, etc.

The file size shows the number of bytes. It is the apparent size, which is the bytes the file uses on a typical disk, without special compression, or special sparse areas, or unallocated blocks, etc.

This script has a production version with more help and more options here: https://github.com/SixArm/sixarm_unix_shell_scripts/blob/master/file-size

share|improve this answer

ls -l filename will give you lots of information about a file, including its file size, permissions and owner.

The file size in the fifth column, and is displayed in bytes. In the example below, the filesize is just under 2KB:

-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php

Edit: This is apparently not as reliable as the stat command.

share|improve this answer
I think both ls -l and stat command give reliable size information. I did not find any reference to the contrary. ls -s will give size in number of blocks. – dabest1 Dec 31 '12 at 22:23
@dabest1 it's not reliable in a sense that in another unix, their output can be different (and in some unixes it is). – Eugene Bujak Oct 2 '14 at 14:39
Yes, IIRC, Solaris didn't display the group name by default, leading to fewer columns in the output. – Edward Falk Apr 4 at 16:31

du filename will tell you disk usage in bytes.

I prefer du -h filename, which gives you the size in a human readable format.

share|improve this answer
that or stat -c "%s" ;) – c00kiemon5ter Jul 13 '11 at 16:29
This flavor of du prints out size in blocks of 1024 bytes, not a simple count of bytes. – Peter Lyons Sep 17 '15 at 5:10

I like the wc option myself. Paired with 'bc,' you can get decimals to as many places as you please.

I was looking to improve a script I had that awk'ed out the 'file size' column of an 'ls -alh' command. I didn't want just integer file sizes, and two decimals seemed to suit, so after reading this discussion, I came up with the code below.

I suggest breaking the line at the semicolons if you include this in a script.

file=$1; string=$(wc -c $file); bite=${string% *}; okay=$(echo "scale=2; $bite/1024" | bc);friend=$(echo -e "$file $okay" "kb"); echo -e "$friend"

My script is called gpfl, for "get picture file length." I use it after doing a mogrify on a file in imagemagick, before opening or re-loading a picture in a GUI jpeg viewer.

I don't know how this rates as an "answer," as it borrows much from what's already been offered and discussed. So I'll leave it there.


share|improve this answer
I would prefer using "stat" or "ls". Typically I don't like using "wc" to get file sizes because it physically reads the entire file. If you have a lot of files, or particularly large files, this can take a lot of time. But your solution is creative...+1. – Kevin Fegan Dec 9 '13 at 19:18
I agree with notion of using "stat" over "wc" for filesize, however if you use "wc -c", no data will be read; instead lseek will be used to figure out the number of bytes in a file. lingrok.org/xref/coreutils/src/wc.c#228 – bbaja42 Dec 14 '14 at 14:38

stat appears to do this with the fewest system calls:

$ set debian-live-8.2.0-amd64-xfce-desktop.iso

$ strace stat --format %s $1 | wc
    282    2795   27364

$ strace wc --bytes $1 | wc
    307    3063   29091

$ strace du --bytes $1 | wc
    437    4376   41955

$ strace find $1 -printf %s | wc
    604    6061   64793
share|improve this answer
What is that set command doing? – Camilo Martin Feb 6 at 11:32
Setting the value of $1. "... The remaining n ARGs are positional parameters and are assigned, in order, to $1, $2, .. $n." – jbm Mar 28 at 20:10

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.