Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在一个监视文件夹中新文件的小脚本中,该脚本似乎找到了错误的文件_Bash_Inotify - Fatal编程技术网

Bash 在一个监视文件夹中新文件的小脚本中,该脚本似乎找到了错误的文件

Bash 在一个监视文件夹中新文件的小脚本中,该脚本似乎找到了错误的文件,bash,inotify,Bash,Inotify,我正在使用此脚本监视正在创建的新.bin文件的下载文件夹。然而,它似乎不起作用。如果我删除了grep,我可以让它复制下载文件夹中创建的任何文件,但是grep不起作用。我怀疑问题在于我如何比较这两个值,但我真的不知道该怎么做 #!/bin/sh downloadDir="$HOME/Downloads/" mbedDir="/media/mbed" inotifywait -m --format %f -e create $downloadDir -q | \ while read line;

我正在使用此脚本监视正在创建的新
.bin
文件的下载文件夹。然而,它似乎不起作用。如果我删除了grep,我可以让它复制下载文件夹中创建的任何文件,但是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

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
将删除除第一行之外的所有内容,这将与
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
这是(IMHO)最简单、最清晰的一个,但它只在bash中有效(即,您必须使用
#!/bin/bash
启动脚本)

其他注意事项:为了避免文件名中可能出现的空格和反斜杠问题,请在IFS=read-r行时使用
;执行
并虔诚地遵循@Sheller关于双引号的建议

另外,我对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

我不清楚它应该做什么。比较的目的是什么?如前所述,它似乎只复制包含“bin”的第一个(按字母顺序排列)文件(不一定以“bin”结尾,因为grep模式没有锚定到行的末尾)。事情,1。始终将未知性质的变量用db引号括起来,即,
“$line”
,如果在
$line
的值中有一个空格,则可能会破坏某些内容,2。打开shell调试,即while循环上方的
set-vx
。然后您将看到每一行/代码块,然后是分配给每个变量的值。然后很容易看出这些失败的地方。如果您不能理解它,请编辑您的帖子以包含相关调试输出。祝你好运。@GordonDavisson比较的目的是只移动与某个正则表达式匹配的文件,尽管我确实忘记了锚定该正则表达式。我不知道如何使inotify只移动符合模式的东西。