Apparently I cannot count. I think there are three files in /media
$ tree /media
/media
├── foo
├── onex
└── zanna
3 directories, 0 files
However, ls -l
finds 12.
$ ls -l /media
total 12
drwxr-xr-x 2 root root 4096 Jul 31 20:57 foo
drwxrwxr-x 2 root root 4096 Jun 26 06:36 onex
drwxr-x---+ 2 root root 4096 Aug 7 21:17 zanna
And, if I do ls -la
I get only .
and ..
in addition to the above, but the count is total 20
What's the explanation?
The
12
you see is not the number of files, but the number of disk blocks consumed.From
info coreutils 'ls invocation'
:The total goes from
12
to20
when you usels -la
instead ofls -l
because you are counting two additional directories:.
and..
. You are using four disk blocks for each (empty) directory, so your total goes from 3 × 4 to 5 × 4. (In all likelihood, you are using one disk block of 4096 bytes for each directory; as theinfo
page indicates, the utility does not check the disk format, but assumes a block size of1024
unless instructed otherwise.)If you want to simply get the number of files, you might try something like
user4556274 has already answered the why. My answer serves only to provide additional information for how to properly count files.
In the Unix community the general consensus is that parsing the output of
ls
is a very very bad idea, since filenames can contain control characters or hidden characters. For example, due to a newline character in a filename, we havels | wc -l
tell us there's 5 lines in the output ofls
(which it does have), but in reality there's only 4 files in the directory.Method #1: find utility
The
find
command, which is typically used for working around parsing filenames, can help us here by printing the inode number. Be it a directory or a file, it only has one unique inode number. Thus, using-printf "%i\n"
and excluding.
via-not -name "."
we can have an accurate count of the files. (Note the use of-maxdepth 1
to prevent recursive descending into subdirectories)Method #2 : globstar
Simple, quick, and mostly portable way:
set
command is used to set positional parameters of the shell ( the$<INTEGER>
variables, as inecho $1
). This is often used to work around/bin/sh
limitation of lacking arrays. A version that performs extra checks can be found in Gille's answer over on Unix&Linux.In shells that support arrays, such as
bash
, we can useas proposed by steeldriver in the comments.
Similar trick to
find
method which usedwc
and globstar can be used withstat
to count inode numbers per line:An alternative approach is to use a wildcard in
for
loop. (Note, this test uses a different directory to test whether this approach descends into subdirectories, which it does not - 16 is the verified number of items in my~/bin
)Method #3: other languages/interpreters
Python can also deal with problematic filenames via printing the length of a list given my
os.listdir()
function (which is non-recursive, and will only list items in the directory given as argument).See also