我正在学习bash脚本,并编写了一个脚本来计算作为参数提供的目录中的文件和目录。我让它以一种对我来说似乎很奇怪的方式工作,我想知道是否有更简单的方法。
我已经注释掉了可以工作的代码,但将其保留为比较。我正在尝试让 for
循环工作,而不是在其中使用if
语句来检测给定位置中的项目是文件还是目录。
编辑:我刚刚发现注释的代码也会计算给定位置的子目录中的所有文件和目录!有没有办法防止这种情况,只计算给定位置的文件和目录?
#!/bin/bash
LOCATION=$1
FILECOUNT=0
DIRCOUNT=0
if [ "$#" -lt "1" ]
then
echo "Usage: ./test2.sh <directory>"
exit 0
fi
#DIRS=$(find $LOCATION -type d)
#FILES=$(find $LOCATION -type f)
#for d in $DIRS
#do
# DIRCOUNT=$[$DIRCOUNT+1]
#done
#for f in $FILES
#do
# FILECOUNT=$[$FILECOUNT+1]
#done
for item in $LOCATION
do
if [ -f "$item" ]
then
FILECOUNT=$[$FILECOUNT+1]
elif [ -d "$item" ]
then
DIRCOUNT=$[$DIRCOUNT+1]
fi
done
echo "File count: " $FILECOUNT
echo "Directory count: " $DIRCOUNT
出于某种原因,无论我将位置指向何处,for
-loop 的输出总是返回:
File count: 0 , Directory count: 1
如下所示使用find
。此解决方案将正确计算带有空格、换行符和点文件的文件名。
FILECOUNT="$(find . -type f -maxdepth 1 -printf x | wc -c)"
DIRCOUNT="$(find . -type d -maxdepth 1 -printf x | wc -c)"
请注意,DIRCOUNT
包括当前目录 ( .
)。如果您不想这样做,请减去 1。
((DIRCOUNT--)) # to exclude the current directory
要解决问题,您可以使用:
FILECOUNT=$(find $LOCATION -type f | wc -l)
DIRCOUNT=$(find $LOCATION -type d | wc -l)
find
将在$LOCATION
下递归查找所有文件(-type f
)或目录(-type d
); wc -l
将计算每种情况下写入 stdout 的行数。
但是,如果您想学习,bash 脚本可能是更好的方法。一些评论:
- 如果您只想在
$LOCATION
中查找文件/目录(而不是在其子目录等下递归),您可以使用for item in $LOCATION/*
,其中*
将展开到$LOCATION
目录中的文件/目录列表。缺少*
是原始脚本返回 0/1 的原因(因为$LOCATION
目录本身是唯一计算的项目)。 - 您可能首先要检查
$LOCATION
实际上是一个包含[ -d $LOCATION ]
的目录。 - 对于算术表达式,请使用
$(( ... ))
,例如FILECOUNT=$(( FILECOUNT + 1 ))
。 - 如果要递归查找所有文件/目录,可以将
find
与循环相结合。
例:
find $LOCATION | while read item; do
# use $item here...
done
您不是在迭代给定目录中的文件列表;而是在 $LOCATION
之后添加/*
。脚本应如下所示:
...
for item in $LOCATION/*
do
...
正如dogbane所指出的,只需添加/*
将仅计算不以.
开头的文件;为此,您应该执行以下操作:
...
for item in $LOCATION/* $LOCATION/.*
do
...
... am wondering if there is a simpler way of doing it.
如果你这么说;)
或者,将脚本缩减为
find /path/to/directory | wc -l
对于当前目录,请执行以下操作:
find . | wc -l
使用
find $LOCATION -maxdepth 1 -type f | wc -l
对于文件计数,以及
find $LOCATION -maxdepth 1 -type d | wc -l
用于计数目录