我想编写一个简单的脚本来检测由 Windows 病毒创建的文件。通常它会创建一个 .exe 文件,与它放置的目录同名。
这是脚本。只有在路径名不包含\n 时才有效。有人可以帮我修复这个脚本,拜托!
#!/bin/bash
if [ $# == 0 ]; then
echo ""
echo "==== Give me a directory to begin with! ===="
echo ""
exit
fi
for f in `find $1 -name '*.exe'` ; do
filename=`basename "$f" .exe`
dir_name=`dirname "$f"`
current_dir_name=`basename "$dir_name"`
if [ $filename == $current_dir_name ]; then
rm -f "$f" # It can't remove files
# where the path contains spaces or \n ??!!
fi
done
Run Code Online (Sandbox Code Playgroud)
Bash 有一个名为 IFS 的特殊变量。
bash 使用它来了解如何将字符串拆分为文件列表。(内部字段分隔符)
默认情况下,它包含空格、制表符和换行符。
for f in `find ...将拆分包含在 $IFS 变量中的字符。如果 find 命令返回的文件名中有换行符或空格,它将被视为不同的文件名,因此将对名称的每个部分执行循环。
$ ls -l -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 my?bad.exe -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 space bad.exe $ for f in $(find -name "*.exe"); 做回声“迭代($ f)”;完毕 迭代(./空格) 迭代 (bad.exe) 迭代 (./my) 迭代 (bad.exe)
我们可以调整 $IFS 变量,但这很棘手。让我们看看为什么:
(在脚本中测试此代码,以便 IFS 变量的更改不会保留在您的 shell 中,您可能会感到困惑)
$ IFS=""; for f in $(find -name "*.exe"); 做回声“迭代($ f)”;完毕 迭代 (./space bad.exe 。/我的 坏.exe)
如您所见,现在 bash 没有任何规则来拆分 find 命令返回的字符串,并将整个输出视为单个值。
显然,这里的问题是,如果我们使用,for f in `find....我们无法区分文件中包含的换行符和 find 命令生成的换行符。
现在,为了完整起见,我将向您展示如何使您的方法有效,但请在答案末尾查看更简单的解决方案。
我们可以使用其他分隔符来解决您当前的问题:
$ for f in $(find -name "*.exe" -exec echo -n {}: \;); 做回声“迭代($ f)”;完毕;
迭代 (./space bad.exe)
迭代 (./my
坏.exe)
迭代 ()
此处该find -name "*.exe" -exec echo -n {}: \;命令返回以“:”分隔的文件列表(在 Windows 文件名中不合法)。
现在下一步是实际删除这些文件。考虑到最后一个文件以“:”结尾,因此 bash 最后一次使用空字符串进行迭代。
IFS=":"; for f in $(find -name "*.exe" -exec echo -n {}: \;); 如果 [ ! -z "$f" ]; 然后 rm "$f"; fi; 完毕;
您应该也可以像以前一样在此循环中执行 basename/dirname 测试。
然而,这个解决方案是丑陋的,并且仅仅因为我们有一个我们可以依赖的角色。
事实证明,find 命令本身可以为它找到的每个文件执行命令。
find -name "*.exe" -exec ./yourscript.sh {} \;
然后 yourscript.sh 将在 $1 中获取全名,rm "$1"即使它包含换行符和空格,您也可以删除。
find 命令还可用于执行您在脚本中执行的内联 basename/dirname 测试,但它是更高级的主题。