You should use this, I think. As I've just found out, it's a POSIX-specified standard utility.
du
The POSIX-specified options include:
The du utility shall conform to XBD Utility Syntax Guidelines .
The following options shall be supported:
-a In addition to the default output, report the size of each file not of type directory in the file hierarchy rooted in the specified file. Regardless of the presence of the -a option, non-directories given as file operands shall always be listed. -H If a symbolic link is specified on the command line, du shall count the size of the file or file hierarchy referenced by the link. -k Write the files sizes in units of 1024 bytes, rather than the default 512-byte units. -L If a symbolic link is specified on the command line or encountered during the traversal of a file hierarchy, du shall count the size of the file or file hierarchy referenced by the link. -s Instead of the default output, report only the total sum for each of the specified files. -x When evaluating file sizes, evaluate only those files that have the same device as the file specified by the file operand. Specifying more than one of the mutually-exclusive options -H and -L shall not be considered an error. The last option specified shall determine the behavior of the utility.
The problem with that though is that it doesn't report on file-size, it reports on disk-usage. They are different concepts and the differences are file-system dependent. If you wanted to get the files sizes for a set of files you might use something like the following:
{ echo /usr/bin/ls -ndL .//* } | sed '/\n/P;//D;N \|//|s|\n|/&/| $s|$|/|;s| .//|/\ /|;2!P;D'
It's a fairly simple-minded bit of sed that maintains a two-line addressable window on ls's output. It works by sliding through its input - always Printing then Deleting the oldest of the two lines in its pattern space then pulling in the Next input line to replace it. It's a one-line lookahead, basically.
It has some major deficiencies as written. For instance, for my own convenience I avoided handling ls's -> linkpath and use the -L option instead which makes ls report on the link target rather than the link itself. It also assumes only current directory globs. It depends on the / not occurring in the filenames - because it is the separator. This is actually fairly common for this kind of stuff - you cd into the directory and cd - back out.
All of that could be handled maybe in a few lines or more, but it's just a demo.
The key component here - and the reason for the lookahead - is this bit:
\|//|s|\n|/&/|
When the newest line in pattern space contains the string .// append a / to the tail of the oldest line and inject a / at the head of the newest. I also then replace the .// with another \newline and two more line-delimiting slashes.
And so this:
drwxr-xr-x 1 1000 1000 6 Aug 4 14:40 .//dir* drwxr-xr-x 1 1000 1000 0 Aug 4 14:40 .//dir1 drwxr-xr-x 1 1000 1000 6 Aug 8 17:34 .//dir2 drwxr-xr-x 1 1000 1000 22 Aug 10 18:12 .//dir3 drwxr-xr-x 1 1000 1000 16 Jul 11 21:59 .//new -rw-r--r-- 1 1000 1000 8 Aug 20 11:32 .//newfile -rw-r--r-- 1 1000 1000 0 Jul 6 11:24 .//new file -rw-r--r-- 1 1000 1000 0 Jul 6 11:24 .//new file link
Becomes this:
/drwxr-xr-x 1 1000 1000 6 Aug 4 14:40/ /dir*/ /drwxr-xr-x 1 1000 1000 0 Aug 4 14:40/ /dir1/ /drwxr-xr-x 1 1000 1000 6 Aug 8 17:34/ /dir2/ /drwxr-xr-x 1 1000 1000 22 Aug 10 18:12/ /dir3/ /drwxr-xr-x 1 1000 1000 16 Jul 11 21:59/ /new/ /-rw-r--r-- 1 1000 1000 8 Aug 20 11:32/ /newfile/ /-rw-r--r-- 1 1000 1000 0 Jul 6 11:24/ /new file/ /-rw-r--r-- 1 1000 1000 0 Jul 6 11:24/ /new file link/
But what use is that, right? Well, it makes all the difference:
IFS=/; set -f; set $(set +f { echo /usr/bin/ls -ndL .//* }| sed '/\n/P;//D;N \|//|s|\n|/&/| $s|$|/|;s| .//|/\ /|;2!P;D' ) unset IFS while [ -n "$2" ] do printf 'Type :\t <%.1s>\tSize :\t %.0s%.0s%.0s<%d>%.0s%.0s%.0s\nFile :\t %s\n' \ $2 "<$4>" shift 4; done
OUTPUT
Type : <d> Size : <6> File : <dir*> Type : <d> Size : <0> File : <dir1> Type : <d> Size : <6> File : <dir2> Type : <d> Size : <22> File : <dir3> Type : <d> Size : <16> File : <new> Type : <-> Size : <8> File : <newfile> Type : <-> Size : <0> File : <new file> Type : <-> Size : <0> File : <new file link>
wcgenerally does astat(and alseekto leave the cursor at the end) for regular files. The only notable exception I'm aware of is busyboxwcand old implementations on some systems (can't remember which now).wcif you want a cross-OS solution. At least the SVR4wcused on Solaris 10 reads the whole file.function x {is thekshsyntax. The Bourne and POSIX syntax isx() {.