Why Count Differs Between Ls and Ls -L Linux Command

Why count differs between ls and ls -l linux command?

From man ls:

-l      (The lowercase letter ``ell''.)  List in long format.  (See below.)  If the output is to a terminal, a total sum for all the file sizes is output on a line before the
long listing.

So ls -l adds a header line stating the "total" size of files:

$ ls -l /
total 65
-r--r--r-- 1 root wheel 6197 May 11 21:57 COPYRIGHT
drwxr-xr-x 2 root wheel 1024 Jun 1 16:02 bin
drwxr-xr-x 9 root wheel 1536 Jun 1 16:02 boot
dr-xr-xr-x 8 root wheel 512 Jul 7 20:16 dev
.......

How to count all the files using ls -l statements separated by && in a single line?

First, you need to use -d option for ls, to make it not to expand the items that are directories and show all the files inside them. Second you need to cut the first line (the one that shows Total 45 at the top). Third using

ls -l *.xml && ls -l *.json && ls -l *.md 

is equivalente to

ls -l *.xml *.json *.md

so you can avoid two calls to ls and two processes.

There's still an issue with ls and it is that you can have no *.xml files, and you will get (on stderr, that is) a *.xml: no such file. This is because the * wildcard expansion is made at the shell, and it is passed verbatim if the shell is unable to find any file with that name.

So, finally, a way to do so would be:

ls -ld *.xml *.json *.md | tail +1 | wc -l

Note:

I shouldn't use -l option, it makes your search more difficult (ls takes more time as it has to stat(2) each file, it outputs the annoying Total blocks line at the top, that you have to eliminate, and you get a blank line between directory listings --this feature is eliminated if you specify option -d-- that you should have to eliminate also). It will skip unreadable files (as the unreadable files cannot be stat(2)ed for info, and you are not using the extra information for anything. You can use just

ls -d *.xml *.json *.md | wc -l

to get only the names (and also strip the used blocks line at the top) that match the patterns you put in the command line. If the output of ls is piped to another command, then it doesn't group the output in columns, as it does when outputting to a terminal.

Anyway, if I had to use some tool to count files, I should use find(1), instead (it allows far more flexibility on files selection, and allows you to search recursively a directory structure) as in:

find . \( -name "*.xml" -o -name "*.json" -o -name "*.md" \) -print | wc -l

or, if you want it to be only in the current directory, just add the option -depth 1 and you will not get it searching recursively into directories.

find . -depth 1 \( -name "*.xml" -o -name "*.json" -o -name "*.md" \) -print | wc -l

Why doesn't total from ls -l add up to total file sizes listed?

You can find the definition of that line in the ls documentation for your platform. For coreutils ls (the one found on a lot of Linux systems), the information can be found via info coreutils ls:

For each directory that is listed, preface the files with a line
`total BLOCKS', where BLOCKS is the total disk allocation for all
files in that directory.

File count - os.listdir vs ls | wc -l

In Linux/UNIX, ls hides file names starting with a dot . unless you specify the -a option, so it's apparent that you have one file in the Images directory that starts with ., which os.listdir would account for but ls would not.

Counting total files in directory - find vs ls

The first command...

find . -mindepth 1 -maxdepth 1 | wc -l

...will list files and directories that start with ., while your ls command will not. The equivalent ls command would be:

ls -A | wc -l

Both will give you the same answers. As folks pointed out in the comments, both of these will give you wrong answers if there are entries that contained embedded newlines, because the above commands are simply counting the number of lines of output.

Here's one way to count the number of files that is independent of
filename quirks:

find . -mindepth 1 -maxdepth 1 -print0 | xargs -0i echo | wc -l

This passes the filenames to xargs with a NUL terminator, rather than relying on newlines, and then xargs simply prints a blank line for each file, and we count the number of lines of output from xargs.



Related Topics



Leave a reply



Submit