使用带有变量的 rm 命令的危险

使用带有变量的 rm 命令的危险

我正在创建一个 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中使用该变量,您不仅可以确保正在操作的日期字符串不会更改,而且可以还可以在任一命令之前测试零长度变量,并且(如果您有零长度字符串)在执行您不想执行的操作之前退出。avimergerm

答案2

有两件事跳出来:

  1. 您没有检查替换失败的情况
  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/

相关内容