1

我正在使用此脚本来监视下载文件夹中是否.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
4

1 回答 1

2

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