这ls $downloadDir -a1 | grep '[^.].*bin' | head -1
是错误的做法。要了解原因,假设您在下载目录中有名为a.txt
andb.bin
的文件,然后c.bin
被添加。inotifywait
将打印c.bin
,ls
将打印a.txt\nb.bin\nc.bin
(使用实际换行符,而不是 \n),grep
将其细化到b.bin\nc.bin
,head
将删除除第一行以外的所有b.bin
内容,这将不匹配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