I am trying to use ls and grep to get the directory count, and store the value in a variable. Unfortunately I am getting this error: ./test.sh: line 3: -l: command not found Here is the script:

#!/bin/bash

assetid=ls -l /home/user/Desktop/folder | grep -c "^d"

echo $assetid

marked as duplicate by PesaThe, tripleee bash Sep 4 at 3:16

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 2
    Why not parse ls? – Cyrus Sep 3 at 21:17
  • I suggest: assetid=$(find . -maxdepth 1 -type d | wc -l) – Cyrus Sep 3 at 21:19
  • @Cyrus That's just as bad as parsing ls; a directory name can contain a newline, so line count != file count. – chepner Sep 3 at 21:32
  • @chepner: That is indeed an important point. – Cyrus Sep 3 at 21:55
up vote 1 down vote accepted

I guess this will handle all cases:

find . -maxdepth 1 -type d -exec echo \; | wc -l

For each dir I print an empty newline... then count the newlines. Sadly wc does not work on null terminated strings, but we could remove all except zeros and count them:

find . -maxdepth 1 -type d -print0 | tr -cd '\0' | wc -c

As to your script, you are getting the error, because you need to enclose to comment in $( .. ) if you want to save it's output into a variable. Bash is space aware, I mean a=1 is assigment, and a = 1 is run program named a with arguments = and 1. Bash interprets the line: var=1 bash -c 'echo $var' as first it sets var=1 then runs the program bash with arguments -c and 'echo $var'. Try this:

assetid=$(ls -l /home/user/Desktop/folder | grep -c "^d")

But don't parse ls output. ls is for human readable nice colored output, it's better to prefer using different utilities in batch/piped scripts.

Use a loop an explicitly count each item resulting from a pattern.

count=0
for f in /home/user/Desktop/folder/*/; do
    count=$((count + 1))
done

If you need to include hidden directories as well, use

count=0
for f in /home/user/Desktop/folder/*/ /home/user/Desktop/folder/.*/; do
    count=$((count + 1))
done

If you aren't concerned about memory usage, fill an array and get the size of the resulting array

dirs=( /home/user/Desktop/folder/*/ )
count=${#dirs[@]}

Sometimes SO formatting is off, but are you really trying to run the command: assetid=ls -l /home/user/Desktop/folder | grep -c "^d"?

If so, that is attempting to run the command -l with the environment variable assetid set to the string ls. You probably intended to do

assetid=$( ls -l /home/user/Desktop/folder | grep -c "^d" )

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