所以我正在编写一个简单的脚本来检查文件的大小是否小于给定的参数,如果为真则假设回显“YES”
#!bin/bash
Function ()
{
cd $1
lista=`ls`
for item in $lista
do
if [ ! -d $item ]
then
size=`wc -c $item | awk '{ print $1 }'`
if [ $size -lt $2 ]
then
echo "$item"
fi
else
Function $item $2
fi
cd ..
done
}
Function $1 $2
还有狂欢:
bash test2.sh /home/161161 300
然而 wc -c 出了点问题,因为它给了我一个错误,即在运行第二个循环后没有这样的文件或不存在。
有任何想法吗?
答案1
问题是您的代码cd ..
在完成目录中的所有文件之前就已经完成了。一般来说,您不必cd
进入目录即可从中获取文件名,并且在循环中来回进入目录可能会令人困惑。如果您在循环内将输出重定向到具有相对路径等的文件名,它也可能会导致奇怪的问题。在这个脚本中,你也不会知道在哪里(在哪个目录中)找到文件,因为你总是在当前目录中查找。
通过不使用cd
和 不使用 来修复此问题ls
,这允许脚本使用包含空格和其他异常字符的文件名:
#!/bin/sh
find_smaller () {
dir=$1
size=$2
for pathname in "$dir"/*; do
if [ -f "$pathname" ]; then
# this is a regular file (or a symbolic link to one), test its size
filesize=$( wc -c <"$pathname" )
if [ "$filesize" -lt "$size" ]; then
printf 'Found %s, size is %d\n' "$pathname" "$filesize"
fi
elif [ -d "$pathname" ]; then
# this is a directory (or a symbolic link to one), recurse
printf 'Entering %s\n' "$pathname"
find_smaller "$pathname" "$size"
fi
done
}
find_smaller "$@"
在上面的代码中,$pathname
不仅是我们正在查看的当前文件或目录的文件名,而且是其相对于起始目录的路径。
另请注意所有变量扩展的引用。$pathname
例如,如果文件名包含*
或等字符,则在不引用变量的情况下,您将调用文件名通配?
。
也可以看看:
使用bash
及其globstar
shell 选项。设置此选项后,**
全局模式将匹配给定目录下的所有路径名。这意味着我们不必在脚本中显式遍历目录结构:
#!/bin/bash
dir="$1"
size="$2"
shopt -s globstar
for pathname in "$dir"/**; do
[ ! -f "$pathname" ] && continue
filesize=$( wc -c <"$pathname" )
if [ "$filesize" -lt "$size" ]; then
printf 'Found %s, size is %d\n' "$pathname" "$filesize"
fi
done
您可以使用find
.以下find
命令执行您的代码尝试执行的操作:
find /home/161161 -type f -size -100c
作为脚本:
#!/bin/sh
dir=$1
size=$2
find "$dir" -type f -size -"$size"c
显式目录遍历器和find
变体之间唯一的细微差别是find
(如上使用时)将忽略符号链接,而其上方的 shell 函数将解析符号链接,可能导致目录循环无限遍历,或者相同的数据被计算多次。
使用find
,将不会读取文件的内容来计算文件大小。相反,lstat()
将调用库来查询文件系统的文件大小。这是许多比使用快数倍wc -c
!
在大多数(但不是全部)Unice 上,您还可以使用命令行实用程序stat
来获取文件大小。请参阅您系统上该实用程序的手册,了解如何使用它(它在 Linux 和 BSD 上的工作方式不同)。