Here's a simple way to do this that should work with the Bourne shell and its descendants (including bash and ksh), if you don't care too much about the exact output format:
$ for file in *; do if [ -f "$file" ] && [ -r "$file" ]; then wc -c "$file"; fi; done
23 HEAD
111 config
73 description
If you also don't care too much about errors and corner cases (in which case, good luck to you):
$ for file in *; do wc -c $file; done
Notes:
If you're writing this with bash or ksh, you're probably better off using ((
))
or [[
]]
instead of [
]
. (source)
Also, below, consider using $(wc -c <"$file")
instead of `wc -c <"$file"`
). (source)
-f
tests to see if what you're looking at is an ordinary file (not a directory, device, pipe, socket, tty, or generally some weird thing that can't be said to have a size in bytes). -r
tests that the file is readable, i.e., that wc
has a chance of succeeding; if you're looking at huge files or files that you can't read, use stat
as per your original version and Stéphane's answer.
The quotes ("$file"
) are necessary if any of the files have spaces or tabs in them (e.g., a file named my stuff.txt
).
If you do care about the exact format, you should probably use some combination of `wc -c <"$file"`
(which will not print the filename) and echo
or echo -n
(which will print whatever you'd like).
If the files of interest are arguments to a script, in that script use "$@"
(explanation).
I agree with @stéphane-chazelas that you shouldn't parse the output of ls
; but if you do, you don't need process substitution. You can more simply read the output of the command:
ls | while IFS= read -r
blah blah blah
or, if you want to recurse through a directory:
find
blah -type f -print | while IFS= read -r
blah blah
or better still:
find
blah -type f print0 | xargs -o
blah blah
where -print0
and xargs -0
again properly handle filenames with spaces or tabs
byte=$(....
-- get rid of the spaces around the=
sign. – Stephen Harris Oct 06 '18 at 20:40