我正在创建一个 crontab,将安全摄像头中的 15 分钟剪辑压缩为一个文件(24 小时长),然后删除这些剪辑。
avimerge -o /media/jmartin/Cams/video/Full_$(date +%F --date "Yesterday") -i /media/jmartin/Cams/video/$(date +%F --date "Yesterday")* # Converts files from the past 24 hours into one .avi
rm /media/jmartin/Cams/video/$(date +%F --date "Yesterday")* # Removes old clips that have already been compressed
我的问题是使用 $date 变量有什么危险。是否可能会发生删除 /video/ 中所有文件的情况?作为更安全的替代方案,您会推荐什么?
文件名示例(是的,这些是文件名中的空格):
2016-04-25 00:00:01.avi
2016-04-25 00:15:02.avi
2016-04-25 00:30:02.avi
2016-04-25 00:45:01.avi
答案1
从$(date +%F --date "Yesterday")
技术上讲,它不是变量,而是命令替换,但这与您的问题无关。如果由于某种原因该date
命令不在您的 中,并且因此没有返回任何内容,则此构造可能会出现问题$PATH
- 此时它将删除 中的所有内容/video/
。如果您采用该命令替换并将其分配给命令之前的变量,然后在和命令avimerge
中使用该变量,您不仅可以确保正在操作的日期字符串不会更改,而且可以还可以在任一命令之前测试零长度变量,并且(如果您有零长度字符串)在执行您不想执行的操作之前退出。avimerge
rm
答案2
有两件事跳出来:
- 您没有检查替换失败的情况
- 如果命令的使用之间的日期发生变化,则存在竞争条件
date
。
你可以像这样解决它们:
#/bin/bash
# Exit if any command fails
set -e
dir='/media/jmartin/Cams/video'
day=$(date +%F --date Yesterday)
# Conbine files from the past 24 hours into a single AVI file
avimerge -o "$dir/Full_$day" -i "$dir/$day"*
# Remove old clips that have already been compressed
rm "$dir/$day"*
答案3
由于您的文件名中始终有空格,因此我会将其包含在您的命令中:
rm "$(date +%F --date "Yesterday") "* # Removes old clips
这应该是防止删除目录中所有文件的简单方法,因为即使date
不返回任何内容,它也只会删除以空格字符开头的文件(希望不存在)。
然而,还有其他一些危险,例如
avimerge
可能会以某种方式失败,并且您最终会删除尚未合并的文件...avimerge
可能需要相当长的时间,随着时间的rm
推移,昨天就是今天,你最终删除了错误的东西......
基本上,盲目相信这些命令做了您想要的事情是一个坏主意。对于自动删除,您应该检查并仔细检查所有内容,并确保正确使用变量。
您应该将date
结果放入实际变量中,检查变量的外观,然后对两个命令使用相同的变量,这样它就不会在两者之间发生变化。
您应该检查您调用的命令的返回代码(退出代码),并且仅在它们没有返回错误时才继续(或者专门处理您期望的错误)。
您应该检查合并文件是否已创建并且具有实际的文件大小。
答案4
只要你的脚本正确并且不在奇怪的环境中运行它,一切都应该没问题。
但如果有什么事情打破了 的预期输出date
,那么所有的赌注都会失败。例如,如果您使用 运行此代码片段IFS=-
,那么您将运行类似的内容
rm /media/… 04 26*
即删除以26
当前目录中以 开头的文件。当然,这只是由于您的脚本中的菜鸟错误:您忘记了命令替换周围的双引号。
rm "/media/jmartin/Cams/video/$(date +%F --date "Yesterday")"*
这至少保证不会删除目标目录之外的文件。
更安全的方法是进行分阶段清理。这样,如果出现问题,您就有时间注意到。
#!/bin/sh
set -e
cd /media/jmartin/Cams/video
if [ -d yesterday ]; then
find yesterday -type f -delete
else
mkdir yesterday
fi
mv "$(date +%F --date "Yesterday") "* yesterday/