我想编写一个简单的脚本来检测由 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
Bash 有一个称为 IFS 的特殊变量。
bash 使用它来了解如何将字符串拆分为文件列表。(内部场分离器)
默认情况下,它包含空格、制表符和换行符。
for f in `find ...
将拆分 $IFS 变量中包含的字符。如果 find 命令返回的文件名中有换行符或空格,则会将其视为不同的文件名,因此将对名称的每个部分执行循环。我们可以调整 $IFS 变量,但这很棘手。让我们看看为什么:
(在脚本中测试此代码,以便 IFS 变量的更改不会保留在您的 shell 中,您可能会感到困惑)
如您所见,现在 bash 没有任何规则来拆分 find 命令返回的字符串,并将整个输出视为单个值。
显然这里的问题是,如果我们使用
for f in `find....
我们无法区分文件中包含的换行符和 find 命令生成的换行符。现在为了完整起见,我将向您展示如何使您的方法起作用,但请在答案末尾查看更简单的解决方案。
我们可以使用其他分隔符来解决您当前的问题:
这里
find -name "*.exe" -exec echo -n {}: \;
命令返回用“:”分隔的文件列表(在 windows 文件名中是不合法的)。现在下一步将是实际删除这些文件。考虑到最后一个文件由“:”终止,因此 bash 最后一次迭代一个空字符串。
您应该能够在此循环中执行您的基本名称/目录名称测试,就像您之前所做的那样。
然而,这个解决方案是丑陋的,只是因为我们有一个可以依赖的角色。
事实证明,find 命令本身可以为它找到的每个文件执行命令。
然后 yourscript.sh 将在 $1 中获得全名,
rm "$1"
即使它包含换行符和空格,您也可以删除。find 命令还可用于执行您在脚本中执行的内联基本名称/目录名称测试,但它是更高级的主题。
这将处理包含文件名中允许的任何字符的文件名,包括换行符。
有关详细信息,请参阅http://mywiki.wooledge.org/BashFAQ/020和http://mywiki.wooledge.org/BashFAQ/100。
您实际上可以
( *.exe )
使用bash
.(
像这样在模式周围加上括号)
意味着它将被扩展并存储在一个数组中。然后,您可以使用以下方法遍历数组中的每个项目:
这是一个完整的例子:
我只能在您澄清您的目录结构后提供完整的解决方案,因为我不确定是否
current_dir_name
正在做您认为的事情。