在一个小的脚本监视新文件的文件夹,该脚本似乎找到了错误的文件 [英] In a small script to monitor a folder for new files, the script seems to be finding the wrong files
问题描述
我使用这个脚本来监视正在创建新的的.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屋!