在用于监视新文件的文件夹的小脚本中,脚本似乎找到了错误的文件

时间:2011-11-16 22:12:34

标签: bash inotify

我正在使用此脚本来监视正在创建的新.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

1 个答案:

答案 0 :(得分:2)

ls $downloadDir -a1 | grep '[^.].*bin' | head -1是错误的做法。要了解原因,假设您在下载目录中有名为a.txtb.bin的文件,然后添加了c.bininotifywait将打印c.binls将打印a.txt\nb.bin\nc.bin(使用实际换行符,而不是\ n),grep会将其缩小为b.bin\nc.binhead会删除除b.bin之外的所有内容,c.bin$line不匹配。您需要检查.bin以查看它是否以$line结尾,而不是扫描目录列表。我会告诉你三种方法:

第一个选项,使用grep检查if echo "$line" | grep -q '[.]bin$'; then ,而不是列表:

-q

请注意,我使用.选项来压缩grep的输出,而只是让if命令检查其退出状态(如果找到匹配则成功,否则失败)。此外,RE被锚定到行的末尾,并且句点在括号中,因此它仅匹配实际句点(通常,正则表达式中的\.bin$匹配任何单个字符)。 $line也适用于此。

第二个选项,使用shell编辑变量内容的功能,以查看.binif [ "${line%.bin}" != "$line" ]; then 是否结束:

"${line%.bin}"

.bin部分给出$ line的值,如果它在那里,则从末尾修剪$line。如果这与$line本身不同,那么.bin必须以[[ ]]结尾。

第三个选项,使用bash的if [[ "$line" == *.bin ]]; then 表达式直接进行模式匹配:

#!/bin/bash

这是(恕我直言)最简单,最清晰的一群,但它只适用于bash(即你必须用while IFS= read -r line; do启动脚本。)

其他说明:为避免文件名中的空格和反斜杠出现问题,请使用-e create并遵循@ shellter关于双引号的建议。

另外,我对inotifywait不是很熟悉,但AIUI的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 。如果这不是您想要的,您应该添加如下内容:

{{1}}