我正在使用此脚本来监视正在创建的新.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
答案 0 :(得分:2)
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
会删除除b.bin
之外的所有内容,c.bin
与$line
不匹配。您需要检查.bin
以查看它是否以$line
结尾,而不是扫描目录列表。我会告诉你三种方法:
第一个选项,使用grep检查if echo "$line" | grep -q '[.]bin$'; then
,而不是列表:
-q
请注意,我使用.
选项来压缩grep的输出,而只是让if命令检查其退出状态(如果找到匹配则成功,否则失败)。此外,RE被锚定到行的末尾,并且句点在括号中,因此它仅匹配实际句点(通常,正则表达式中的\.bin$
匹配任何单个字符)。 $line
也适用于此。
第二个选项,使用shell编辑变量内容的功能,以查看.bin
中if [ "${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}}