9

I know I can use ls -lat to find out how many bytes has a file and then multiply by 8 to find out how many bits. But is this possible in only one command line?

4

5 Answers 5

16

With GNU du:

du -b FILE | awk '{ print $1 * 8 }'
2
  • 10
    Except it doesn't need bc - awk can do math itself: du -b FILE | awk '{print $1 * 8}
    – aragaer
    Jan 27, 2014 at 1:23
  • 1
    See also wc -c < FILE for a portable equivalent (for non-regular files, it has the side-effect of reading them, though) Jan 27, 2014 at 8:45
5

A shell + GNU coreutils solution:

echo $(( 8 * $(stat -c%s FILE) ))

The -c%s option to stat returns just the file size in bytes, eliminating any need for additional text processing. This syntax is supported by GNU coreutils and therefore should work under most linux distributions.

As an exception on linux, if one is running zsh with the optional zsh/stat module, then one needs to specify a path to get the GNU coreutils:

echo $(( 8 * $(command stat -c%s FILE) ))
3
  • @StephaneChazelas Thanks for the info. Answer updated.
    – John1024
    Jan 26, 2014 at 23:30
  • It seems a good explanation, thank you. However in my test this command returned to me: title:7: bad math expression: operand expected at `%s ' ]2;echo 4096000 ---- the answer is 4096000, but what are the other errors?
    – Felipe
    Jan 26, 2014 at 23:49
  • @FelipeMicaroniLalli I cannot reproduce that error and I do not see any circumstance that would both (a) give that error message, and, at the same time, (b) give the right numerical answer. Curious.
    – John1024
    Jan 27, 2014 at 0:24
3

With GNU find (predates GNU stat by decades):

find file -prune -printf '%s*8\n' | bc

Relatively portably:

ls -ld -- "$file" | awk '{print $5*8;exit}'
3

It is possible in one line, because you can put several commands on one line, e.g. connected by pipes or command substitutions:

echo $(stat -c %s FILE) '* 8' | bc

(Thanks @frostschutz for the update).

3
  • Worked like a charm to me. ➜ tmp stat random-file-3 | sed -n 's/Size: ([0-9]*).*/\1 * 8/p' | bc ➜ 4096000
    – Felipe
    Jan 26, 2014 at 23:49
  • Won't work in non-English locales or on non-GNU systems or for a file called ZSize: 5 for instance Jan 27, 2014 at 8:51
  • 1
    how about stat -c %s FILE to print size directly, instead of the sed? Jan 27, 2014 at 10:51
2

Single file:

wc -c yourfile | awk '{print $1*8}'

Mutiple files:

wc -c yourfile1 yourfile2 | awk '{$1*=8; print $0}'

This one also works for a single file. It is not completely bulletproof though, see Stephane's comment.

These are POSIX standard compliant commands.

4
  • Great. Awesome. ➜ tmp wc -c random-file-1 random-file-2 random-file-3 | awk '{$1*=8; print $0}' ➜ 32832 random-file-1 ➜ 49152 random-file-2 ➜ 4096000 random-file-3 ➜ 4177984 total
    – Felipe
    Jan 26, 2014 at 23:56
  • 1
    Note that it has side effects if the files are not regular files. The second one would display a a    b file as a b (sequences of blanks converted to a single space, trailing blanks removed). Jan 27, 2014 at 8:48
  • @StephaneChazelas with what kind of non-regular file did you try please?
    – Totor
    Jan 29, 2014 at 8:32
  • Any type (fifos, sockets, doors, devices, directories...). You'll have issues with filenames containing newline characters as well. You may want to add a NR == 1 Jan 29, 2014 at 9:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .