Shell Script to Display Number of Files and Direct

2019-05-18 18:12发布

问题:

I'm trying to write a script that will tell you how many files and how many directories are in a given directory.

Here's the script I've written, but the output is always "Number of files is ." and "Number of directories is ."

Here's my code:

#!/bin/sh
if [ -d "$@" ]
then
find "$@" -type f | ls -l "$@" | wc -l | echo "Number of files is $@"
find "$@" -type d | ls -l "$@" | wc -l | echo "Number of directories is $@"
fi

回答1:

You seem to be confused on piping here.

You want the output of find ... | wc -l to be expanded in the echo command.

So, your script, given what you want to accomplish should look something like this:

#!/bin/sh

if [ -d "$@" ]; then
    echo "Number of files is $(find "$@" -type f | wc -l)"
    echo "Number of directories is $(find "$@" -type d | wc -l)"
else
    echo "[ERROR]  Please provide a directory."
    exit 1
fi


回答2:

You seem to be having difficulties to understand how pipes work. You cannot "natively" use the "result" (stdout) of a pipe (the left-hand side) as a variable on the right-hand side of a pipe, you either need to consume and read it into a variable, e.g.

printf "line1\nline2\n" | while read line; do_stuff_with "${line}"; done

or you need to use command substitution (and optionally assign it to a variable), e.g.

files=$(find "$1" -maxdepth 1 -type f -printf . | wc -c)

A few further notes:

  • $@ expands to all positional parameters, in case of multiple arguments your [ -d "$@" ] will fail.
  • The ls is completely superfluous
  • find works recursively, but I guess you only want the first directory level to be checked so this needs the maxdepth parameter
  • This will break on weird paths with newlines which can be worked around by telling find to print a character for each found directory/file and then count bytes instead of lines

In case you really don't want this to be recursive it might be easier to just use globbing to obtain the desired result:

$ cat t.sh
#!/bin/bash

for file in "${1-.}"/*; do
        [ -d "${file}" ] && ((directories++))
        [ -f "${file}" ] && ((files++))
done

echo "Number of files: ${files-0}"
echo "Number of directories: ${directories-0}"

.

$ ./t.sh
Number of files: 6
Number of directories: 1

$ ./t.sh /tmp
Number of files: 9
Number of directories: 3

You might want to check man test to tweak with regards to links to obtain your desired result.