Iterating over file (and directory) names

2019-02-28 04:55发布

I was trying to write a bash script for counting the number of files and the number of directories of the local directory. This was my first try:

#!/bin/bash
files=0
dir=0
for file in `ls`
do
    if [ -d $file ]
    then
        dir=$(($dir+1))
    else
        files=$(($files+1))
    fi
done 
echo "files=$files, direcotries=$dir"

However, the for command is not iterating over the names of files and directories as I would expect. If the name of the file ou directory has spaces, this does not work well. When there are spaces in the names, the variable "file" assumes the value of each of the words in the file (or directory) name.

Is there any way to do this?

2条回答
三岁会撩人
2楼-- · 2019-02-28 05:19

Use a wild card: for file in *; do …; done. That keeps the spaces in the names correct. Consider shopt -s nullglob too. Neither your code nor my suggestion lists names starting with a dot ..

Also, use if [ -d "$file" ] with double quotes around the variable value to avoid spacing problems.

Hence:

#!/bin/bash

shopt -s nullglob
files=0
dir=0
for file in *
do
    if [ -d "$file" ]
    then
        dir=$(($dir+1))
    else
        files=$(($files+1))
    fi
done 
echo "files=$files, directories=$dir"

In Bash, there are also other ways of writing the arithmetic, such as ((files++)).

查看更多
We Are One
3楼-- · 2019-02-28 05:41

I think that Jonathan Leffler's answer is exactly what you need.

An alternative that shows the power of bash arrays and eliminates the need for loops:

shopt -s nullglob
dirs=(*/)
ndir="${#dirs[@]}"
files=(*)
nfile=$(( "${#files[@]}" - ndir))
echo "files=$nfile, directories=$ndir"

This works as follows:

  • dirs=(*/) creates an array of the names of the directories.

  • ndir="${#dirs[@]}" counts the number of directories.

  • files=(*) creates an array of the names of all files and directories.

  • nfile=$(( "${#files[@]}" - ndir)) computes the number of files by taking the number of elements of files and subtracting from that the number of directories.

  • echo "files=$nfile, directories=$ndir" prints out the results.

This will only work in a shell, like bash, that supports arrays. On many systems, sh is dash which does not support arrays. So, use bash script when executing this script.

查看更多
登录 后发表回答