1. Introduction

Getting the accurate number of filesystem objects under a given path is a common task for many Linux users.

In this tutorial, we’ll discuss the difference between lsls -l, and ls -1 when piping to wc -l for counting the number of files and subdirectories beneath a given directory.

First, we’ll briefly refresh our knowledge about the functionalities of ls and wc. After that, we’ll discuss the output using the different ls variations. Lastly, we’ll look at the comparison between ls | wc -l and ls -1 | wc -l and discuss the results.

2. Overview of ls

We use the ls command to list the files and the directories in the current working directory or at any specified location. In addition, the options of the ls command can customize the output and get essential information such as file permissions, ownership, timestamps, and file size.

Let’s suppose our target is directory1. To view its content, we’ll use ls:

$ ls directory1
directory2 file1.txt file2.txt file3.txt

This way, we get the names of all files and directories in a horizontal format on the terminal separated by spaces or tabs.

To view more details about the directory content, we’ll use the -l option:

$ ls -l directory1
total 4
drwxrwxrwx 1 sidrah sidrah 512 Jul 31 15:54 directory2
-rwxrwxrwx 1 sidrah sidrah 0 Jul 31 15:54 file1.txt
-rwxrwxrwx 1 sidrah sidrah 0 Jul 31 15:54 file2.txt
-rwxrwxrwx 1 sidrah sidrah 0 Jul 31 15:54 file3.txt

Now, we can see information such as owning users and groups, file permissions, file creation date, and file size. Further, each line shows the data for a separate file.

We can do the same, but only for filenames, by using -1 with ls:

$ ls -1 directory1
directory2
file1.txt
file2.txt
file3.txt

This command lists the name of each file and directory on a separate line, which can make it easier to read or parse.

3. Overview of wc

The wc command name stands for word count as it can count lines, words, and characters for a given input. In addition, it can process data from its arguments.

For example, to view the word count of any file, we’ll use the wc command followed by the name of a file:

$ wc filename.txt

This command prints the numbers of lines, words, and characters on the standard output. In this example, we’ve provided the input to the wc command in the form of a filename.

4. Counting ls Output

In this section, we’ll talk about how the ls command processes the output when it goes to a non-terminal STDOUT like a pipe. In particular, we’ll discuss how the output changes when ls is piped to wc using the pipe operator (|).

4.1. Using ls | wc -l

The first method we’ll discuss for counting files uses ls alone and just pipes to wc. We’ll consider the same example we discussed earlier:

$ ls directory1 | wc -l
4

In this command, ls sends the output to wc instead of printing it to the terminal.

Although the ls command usually prints the output in horizontal form, it detects that the output is piped to another command instead of the terminal. Hence, it adjusts its behavior and separates each file and directory name with a newline character (\n).

Because of this, the wc command accurately counts the number of files and directories.

4.2. Using ls -1 | wc -l

In fact, we can use -1 with ls to explicitly instruct the ls command to print the names of filesystem objects on a new line each instead of using the horizontal format:

$ ls -1 directory1 | wc -l
4

The output of ls isn’t displayed directly in the terminal. Instead, it becomes the input for wc where it counts each entry separately. Hence, we can see the correct output, since what wc sees is exactly the same as with our previous example.

4.3. Using ls -l | wc -l

Finally, we’ll use the -l flag with ls and pipe the output to wc:

$ ls -l directory1 | wc -l
5

In this command, the output of ls -l becomes the input for wc -l. As we already saw, this ls output format also consists of one object per line. So, counting each line is what we do with wc -l.

Yet, we can see that the output is 5 instead of 4. That’s because the output from ls -l consists of an extra line: total 4, as shown earlier:

$ ls -l directory1
total 4
drwxrwxrwx 1 sidrah sidrah 512 Jul 31 15:54 directory2
-rwxrwxrwx 1 sidrah sidrah 0 Jul 31 15:54 file1.txt
-rwxrwxrwx 1 sidrah sidrah 0 Jul 31 15:54 file2.txt
-rwxrwxrwx 1 sidrah sidrah 0 Jul 31 15:54 file3.txt

Since all of the output becomes an input for the command after the pipe operator, wc counts that extra line.

5. Comparison Between ls | wc -l and ls -l | wc -l

Although the output from ls | wc -l and ls -1 | wc -l is similar, the first command might produce incorrect results in some shells if the filenames are complex and contain special characters.

For instance, if a directory has a single file with a filename containing a newline, the ls command might interpret the newline character as an actual new line, thus making the line count different from the filesystem object count. In this case, we might get the command output to be 2 when it’s just one file:

$ ls directory1 | wc -l
6

However, the second command, ls -1 | wc -l, accurately counts the files and returns the correct output:

$ ls -1 directory1 | wc -l
5

So, the ls -1 command ensures that each file or directory name is treated as a distinct entry when piped to wc -l. Therefore, we don’t see any issues related to the format when we execute this command. Notably, whether this problem appears depends on the shell interpretation more than the actual command version.

6. Conclusion

In this article, we discussed the difference between ls, ls -l, and ls -1 when it comes to counting objects with wc.

First, we did a brief overview of the ls and wc commands. Next, we discussed the output of ls when piping to wc -l to count the number of files and directories. Lastly, we looked at the comparison between ls | wc -l and ls -1 | wc -l.