在一个小的脚本监视新文件的文件夹,该脚本似乎找到了错误的文件 [英] In a small script to monitor a folder for new files, the script seems to be finding the wrong files

查看:130
本文介绍了在一个小的脚本监视新文件的文件夹,该脚本似乎找到了错误的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用这个脚本来监视正在创建新的的.bin 文件下载文件夹。然而,这似乎并不奏效。如果我删除了grep的,我可以把它复制在下载文件夹中创建的任何文件,而是用grep的它不工作。我怀疑的问题是如何,我想这两个值进行比较,但我真的不知道该怎么做。

 #!/ bin / sh的downloadDir =$ HOME /下载/
mbedDir =/媒体/ mbedinotifywait -m --format%F -e创建$ downloadDir -q | \\
而读线;做
    如果[$(LS $ downloadDir -A1 | grep的'[^] *斌。|头-1)== $线]。然后
        CP$ downloadDir / $行,$ mbedDir / $线
    科幻
DONE


解决方案

LS $ downloadDir -A1 | grep的'[^] *本'|头-1 是错误的方式去了解这一点。要知道为什么,假设你已经命名的文件 A.TXT b.bin 在下载目录,然后 c.bin 加入。 inotifywait 将打印 c.bin LS 将打印 A.TXT \\ nb.bin \\ nc.bin (实际换行,没有的\\ n),的grep 将薄,到 b.bin \\ nc.bin 将删除所有,但第一行离开 b.bin ,这将不匹配 c.bin 。你需要检查 $行,看它是否在的.bin 结尾,而不是扫描目录列表。我给你三种方法来做到这一点:

第一个选项,使用grep来检查 $行,不上市交易:

 如果回声$行| grep的-q'[]斌$';然后

请注意,我使用了 -q 选项来苏preSS的grep的输出,而不是简单地让如果如果命令检查其退出状态(成功找到匹配,失败如果没有)。此外,RE锚定到行的结束,期间在括号所以它会只匹配实际周期(通常情况下,在常规的前pression匹配任何单个字符)。 \\斌$ 也将在这里工作。

第二个选择,使用shell的编辑变量内容的能力,看看 $行的.bin 结尾:

 如果[$ {线路%的.bin}=$行!];然后

$ {线路%的.bin}部分给出了$行与的.bin 值修整从结束时,如果它的存在。如果这是不一样的 $行本身,那么 $行意有所指与结束的.bin

第三种选择,使用bash中的 [[]] 前pression做模式匹配直接:

 如果[$线== * .bin文件]];然后

这是(恕我直言)是最简单和最明确的一群,但它只能在bash(即你必须以剧本#!/斌/庆典

其他注意事项:避免文件名以空格一些可能出现的问题和反斜线,使用而IFS =读-r线;做并关注@ shellter的关于双引号宗教建议。

另外,我不是很熟悉inotifywait,但其AIUI -e创建选项将通知您在创建文件时,而不是在它的内容完全写出。根据不同的时间,你可能结业复制部分写入文件。

最后,你不必重复文件名的任何检查。如果你下载一个名为 foo.bin 会发生什么,它就会被复制,删除原始,然后下载指定不同的文件 foo.bin 。由于脚本是现在,它会静静地覆盖第一个 foo.bin 。如果这不是你想要的,你应该增加类似:

 如果[! -e$ mbedDir / $线];然后
    CP$ downloadDir / $行,$ mbedDir / $线
ELIF! CMP -s$ downloadDir / $行,$ mbedDir / $行;然后
    回声Eeek,重复的文件名! >和2
    #或可能的东西比这更富有建设性...
科幻

I'm using this script to monitor the downloads folder for new .bin files being created. However, it doesn't seem to be working. If I remove the grep, I can make it copy any file created in the Downloads folder, but with the grep it's not working. I suspect the problem is how I'm trying to compare the two values, but I'm really not sure what to do.

#!/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

解决方案

The ls $downloadDir -a1 | grep '[^.].*bin' | head -1 is the wrong way to go about this. To see why, suppose you had files named a.txt and b.bin in the download directory, and then c.bin was added. inotifywait would print c.bin, ls would print a.txt\nb.bin\nc.bin (with actual newlines, not \n), grep would thin that to b.bin\nc.bin, head would remove all but the first line leaving b.bin, which would not match c.bin. You need to be checking $line to see if it ends in .bin, not scanning a directory listing. I'll give you three ways to do this:

First option, use grep to check $line, not the listing:

if echo "$line" | grep -q '[.]bin$'; then

Note that I'm using the -q option to supress grep's output, and instead simply letting the if command check its exit status (success if it found a match, failure if not). Also, the RE is anchored to the end of the line, and the period is in brackets so it'll only match an actual period (normally, . in a regular expression matches any single character). \.bin$ would also work here.

Second option, use the shell's ability to edit variable contents to see if $line ends in .bin:

if [ "${line%.bin}" != "$line" ]; then

the "${line%.bin}" part gives the value of $line with .bin trimmed from the end if it's there. If that's not the same as $line itself, then $line must've ended with .bin.

Third option, use bash's [[ ]] expression to do pattern matching directly:

if [[ "$line" == *.bin ]]; then

This is (IMHO) the simplest and clearest of the bunch, but it only works in bash (i.e. you must start the script with #!/bin/bash).

Other notes: to avoid some possible issues with whitespace and backslashes in filenames, use while IFS= read -r line; do and follow @shellter's recommendation about double-quotes religiously.

Also, I'm not very familiar with inotifywait, but AIUI its -e create option will notify you when the file is created, not when its contents are fully written out. Depending on the timing, you may wind up copying partially-written files.

Finally, you don't have any checking for duplicate filenames. What should happen if you download a file named foo.bin, it gets copied, you delete the original, then download a different file named foo.bin. As the script is now, it'll silently overwrite the first foo.bin. If this isn't what you want, you should add something like:

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

这篇关于在一个小的脚本监视新文件的文件夹,该脚本似乎找到了错误的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆