在监视文件夹中新文件的小脚本中,该脚本似乎正在查找错误的文件
Posted
技术标签:
【中文标题】在监视文件夹中新文件的小脚本中,该脚本似乎正在查找错误的文件【英文标题】:In a small script to monitor a folder for new files, the script seems to be finding the wrong files 【发布时间】:2011-11-16 22:12:34 【问题描述】:我正在使用此脚本来监视下载文件夹中是否有正在创建的新 .bin
文件。但是,它似乎不起作用。如果我删除 grep,我可以让它复制在 Downloads 文件夹中创建的任何文件,但是使用 grep 它不起作用。我怀疑问题在于我如何尝试比较这两个值,但我真的不确定该怎么做。
#!/bin/sh
downloadDir="$HOME/Downloads/"
mbedDir="/media/mbed"
inotifywait -m --format %f -e create $downloadDir -q | \
while read line; do
if [ $(ls $downloadDir -a1 | grep '[^.].*bin' | head -1) == $line ]; then
cp "$downloadDir/$line" "$mbedDir/$line"
fi
done
【问题讨论】:
我不清楚它应该做什么。比较的目的是什么?如所写,它似乎只复制第一个(按字母顺序)包含“bin”的文件(不一定以“bin”结尾,因为 grep 模式未锚定到行尾)。 2.事情,1. 总是用 db-quotes 包围未知性质的变量,即"$line"
如果你在$line
的值中出现一个可能破坏事物的空格,2. 打开 shell 调试,即set -vx
在你的 while 循环之上。然后您将看到每一行/代码块以及分配给每个变量的值。然后很容易看出这些失败的地方。如果您无法弄清楚,请编辑您的帖子以包含相关的调试输出。祝你好运。
@GordonDavisson 比较的目的是只移动与某个正则表达式匹配的文件,尽管我确实忘记锚定所说的正则表达式。我看不出如何让 inotify 只移动与模式匹配的东西。
【参考方案1】:
ls $downloadDir -a1 | grep '[^.].*bin' | head -1
是错误的处理方式。要了解原因,假设您在下载目录中有名为 a.txt
和 b.bin
的文件,然后添加了 c.bin
。 inotifywait
将打印 c.bin
,ls
将打印 a.txt\nb.bin\nc.bin
(带有实际换行符,而不是 \n),grep
会将其细化为 b.bin\nc.bin
,head
将删除除第一行之外的所有内容 @ 987654332@,与 c.bin
不匹配。您需要检查$line
以查看它是否以.bin
结尾,而不是扫描目录列表。我会给你三种方法来做到这一点:
第一个选项,使用 grep 检查$line
,而不是列表:
if echo "$line" | grep -q '[.]bin$'; then
请注意,我使用-q
选项来抑制 grep 的输出,而只是让 if 命令检查其退出状态(如果找到匹配则成功,否则失败)。此外,RE 锚定到行尾,句点在括号中,因此它只会匹配实际的句点(通常,正则表达式中的 .
匹配任何单个字符)。 \.bin$
也可以在这里工作。
第二个选项,利用shell的能力编辑变量内容,看看$line
是否以.bin
结尾:
if [ "$line%.bin" != "$line" ]; then
"$line%.bin"
部分给出了 $line 的值,.bin
如果存在,则从末尾修剪。如果这与$line
本身不同,那么$line
必须以.bin
结尾。
第三种选择,直接使用bash的[[ ]]
表达式进行模式匹配:
if [[ "$line" == *.bin ]]; then
这是(恕我直言)最简单和最清晰的一个,但它只适用于 bash(即您必须以 #!/bin/bash
启动脚本)。
其他注意事项:为避免文件名中的空格和反斜杠出现一些可能的问题,请使用while IFS= read -r line; do
并认真遵循@shellter 关于双引号的建议。
另外,我对 inotifywait 不是很熟悉,但是 AIUI 它的-e create
选项会在文件创建时通知您,而不是在其内容完全写出时通知您。根据时间的不同,您可能会复制部分写入的文件。
最后,您无需检查重复的文件名。如果您下载一个名为foo.bin
的文件,它会被复制,然后删除原始文件,然后下载另一个名为foo.bin
的文件,会发生什么情况。就像现在的脚本一样,它会默默地覆盖第一个foo.bin
。如果这不是您想要的,您应该添加如下内容:
if [ ! -e "$mbedDir/$line" ]; then
cp "$downloadDir/$line" "$mbedDir/$line"
elif ! cmp -s "$downloadDir/$line" "$mbedDir/$line"; then
echo "Eeek, a duplicate filename!" >&2
# or possibly something more constructive than that...
fi
【讨论】:
以上是关于在监视文件夹中新文件的小脚本中,该脚本似乎正在查找错误的文件的主要内容,如果未能解决你的问题,请参考以下文章
如何在一个脚本中监视javascript函数,该脚本被注入jsdom用于测试目的?
在 macOS Catalina 下的 Finder 中查找活动壁纸文件的脚本
我正在尝试编写python脚本来查找超过1000行的文件中的字符串,并在该字符串匹配后删除几行(10)