I have written the script below but it returns 0 for the number of files in the directory now matter how many files are in the directory.

source ~/Alan/assign/changeDir.sh
num=$(( ls | wc -l ))
echo $num

changeDir.sh script is the following

function my_cd() {
cd ~/Alan

All I need is a number to be returned in order for it to be used later in the same script. I would very much appreciate guidance on this. Thanks

  • Do you, by the word "file", mean "regular files", or just any files?
    – Kusalananda
    Apr 28, 2020 at 15:11

3 Answers 3


To find the number of names in a single directory, expand the * glob in it and count the number of generated words:

shopt -s nullglob    # to make the * glob expand to nothing
                     # if there is no matching names
set -- *

printf '%s\n' "$num"

The special value $# is the number of positional parameters. The set command sets the positional parameters.

Would you want to count regular files only, and include hidden names, then use

shopt -s nullglob dotglob

for name in *; do
    if [ ! -f "$name" ] || [ -L "$name" ]; then
        # skip non-regular files and symbolic links
    files+=( "$name" )


printf '%s\n' "$num"

To do that recursively into subdirectories, also set the globstar shell option and use **/* as the globbing pattern.

(in the zsh shell, it would be enough with set -- **/*(.DN); print $#)

The issue with your

num=$(( ls | wc -l ))

is twofold:

  1. $(( ... )) is an arithmetic expansion. You probably want a command substitution here, $( ... ).
  2. The wc -l will not count files. It will count the number of newline characters outputted by ls. A file with one or more newlines in its name will be counted as multiple files by wc -l. You can test this by creating such a file using touch $'hello\nworld'.
  • @pLumo Yes, I chose to write it in this way as that would be what ls by default displays too (used by the user in the question).
    – Kusalananda
    Apr 28, 2020 at 15:09
  • 1
    @pLumo Added a bit about that.
    – Kusalananda
    Apr 28, 2020 at 16:27

If you want to count files including hidden files (.*) , but have subdirectories excluded, you can use:

find . -maxdepth 1 -type f -printf '.' | wc -c

All benefits of find may be used.


I think the problem is a wrong syntax in your command substitution.

The command

num=$(( expression ))

will interpret the content of the parentheses as an arithmetic expression and assign the numerical result to num. It will not return the output of running that which is written inside the parentheses as code. Rather, ls, wc and l will be interpreted as shell variables, and the operation "$ls OR $wc minus $l" be performed, which results in zero as none of these "variables" are initialized.

What you are probably trying to do would be written as

num="$(ls | wc -l)"

However, even so, parsing the output of ls is not a good idea in general. Rather, look at some of the answers to this similar question where "robust" solutions are presented that will also work when filenames contain special characters.

Not the answer you're looking for? Browse other questions tagged or ask your own question.