我有一个场景,其中所有文件模式都放置在文本文件中。现在我需要编写一个 shell 脚本来读取文本文件中存在的每个文件模式名称,并检查它是否存在于目录中。最后应将输出写入日志文件。
#!/bin/ksh
file="/usr/opt/filenames.txt"
mondir=/home/pavan
while read line
do
# display list of files with the pattern in the monitoring directory
filename=$line
ls -lrt $mondir/$filename*
done <"$file"
上面的代码列出了文件。但我还需要打印计数(每个文件模式名称的文件数。
答案1
#!/bin/ksh -
file="/usr/opt/filenames.txt"
mondir=/home/pavan
IFS=
while read -r filepattern
do
set -- "$mondir"/$filepattern*
if [ "$#" -eq 1 ] && [ ! -e "$1" ] && [ ! -L "$1" ]; then
printf '%s\n' "$filepattern: 0"
else
printf '%s\n' "$filepattern: $#"
ls -lrtd -- "$@"
fi
done <"$file"
ksh
,就像 Bourne shell 有一个错误特性,当模式不匹配时,它会扩展到自身。上面,我们使用存在性测试 ( [ -e "$1" ]
) 来检查是否处于不匹配模式的情况,但请注意,它并不是万无一失的。
例如,对于filepattern='[a-z]'
,如果[a-z]*
不匹配任何文件,则未展开的模式 ( [a-z]*
) 实际上可能引用被调用的文件[a-z]*
(与模式不匹配)。
如果您ksh
基于最新版本的ksh93
,您可以使用以下方法修复它:
#!/bin/ksh -
file="/usr/opt/filenames.txt"
mondir=/home/pavan
IFS=
while read -r filepattern
do
set -- "$mondir"/~(N)$filepattern*
printf '%s\n' "$filepattern: $#"
[ "$#" -eq 0 ] || ls -lrtd -- "$@"
done <"$file"
这~(N)
会导致 glob 在不匹配时扩展为空(如N
的 glob 限定符zsh
)。