Depends what you mean by size.
size=$(wc -c < "$file")
will give you the number of bytes that can be read from the file. IOW, it's the size of the content of the file. It will however read the content of the file (except if the file is a regular file or symlink to regular file in most wc
implementations as an optimisation). That may have side effects. For instance, for a named pipe, what has been read can no longer be read again.
That's standard and portable, however note that some wc
implementations may include leading blanks in that output. One way to get rid of them is to use:
size=$(($(wc -c < "$file")))
ksh93
has wc
builtin (provided you enable it, you can also invoke it as command /opt/ast/bin/wc
) which makes it the most efficient for regular files in that shell.
Various systems have a command called stat
that's an interface to the stat()
or lstat()
system calls.
Those report information found in the inode. One of that information is the st_size
attribute. For regular files, that's the size of the content (how much data could be read from it in the absence of error (that's what most wc -c
implementations use in their optimisation)). For symlinks, that's the size in bytes of the target path. For named pipes, depending on the system, it's either 0 or the number of bytes currently in the pipe buffer...
By chronological order, there is:
IRIX
stat
(90's):stat -Ls -- "$file"
returns the st_size
attribute of $file
(lstat()
) or:
stat -s -- "$file"
same except when $file
is a symlink in which case it's the st_size
of the file after symlink resolution.
zsh
stat
builtin (now also known aszstat
) in thezsh/stat
module (loaded withzmodload zsh/stat
) (1997):stat -L +size -- $file # st_size of file stat +size -- $file # after symlink resolution
or to store in a variable:
stat -L -A size +size -- $file
obviously, that's the most efficient in that shell.
GNU
stat
(2001):stat -c %s -- "$file" # st_size of file stat -Lc %s -- "$file" # after symlink resolution
(note the meaning of -L
is reversed compared to IRIX or zsh
stat
.
BSDs
stat
(2002):stat -f %z -- "$file" # st_size of file stat -Lf %z -- "$file" # after symlink resolution
AIX also has an istat
command which will dump all the stat()
/lstat()
information and which you could post-process with, for example:
istat "$file" | awk '/Length/ { print $5 }'
Long before GNU introduced its stat
command, the same could be achieved with GNU find
command with its -printf
predicate (already in 1991):
find -- "$file" -prune -printf '%s\n' # st_size of file
find -L -- "$file" -prune -printf '%s\n' # after symlink resolution
One issue though is that doesn't work if $file
starts with -
or is a find
predicate (like !
, (
...).
The standard command to get the stat()
/lstat()
information is ls
.
POSIXly, you can do:
LC_ALL=C ls -dn -- "$file" | awk '{print $5; exit}'
and add -L
for the same after symlink resolution.
For block device, stat()
returns 0 for st_size
. Some systems have other APIs to report the size of the block device. For instance, Linux has the BLKGETSIZE64
ioctl()
, and most Linux distributions now ship with a blockdev
command that can make use of it:
blockdev --getsize64 -- "$device_file"
However, you need read permission to the device file for that. It's usually possible to derive the size by other means. For instance (still on Linux):
lsblk -bdno size -- "$device_file"
Should work except for empty devices.
An approach that works for all seekable files (so includes regular files, most block devices and some character devices) is to open the file and seek to the end:
With
zsh
(after loading thezsh/system
module):{sysseek -w end 0 && size=$((systell(0)))} < $file
With
ksh93
:: < "$file" <#((size=EOF))
with
perl
:perl -le 'seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN' < "$file"
For named pipes, we've seen that some systems make the amount of data in the pipe buffer available in stat()
's st_size
. That's rare though.
On Linux at least, you can use the FIONREAD
ioctl()
:
perl -le 'require "sys/ioctl.ph";
ioctl(STDIN, &FIONREAD, $n) or die$!;
print unpack "L", $n' <> "$fifo_file"
However note that while it doesn't read the content of the pipe, the mere opening of a named pipes can have side effects.