我正在尝试创建一个例程来管理我正在创建的备份文件,以便在此过程中自动删除旧文件夹。这是我所得到的:
#!/bin/sh
day=$(date +%m%d%y)
oldday=$(date -d "-4 days" +%m%d%y)
mkdir /home/fauna/backup/$day
rm -r /home/fauna/backup/$oldday
cp /home/fauna/backup/backup.sh /home/fauna/backup/$day
cd /home/fauna/backup/$day
./backup.sh
backup.sh
实际上创建备份文件,然后将包含这些文件的文件夹复制到远程位置。
该rm
行会删除旧文件夹而不会产生任何意想不到的后果吗?
我可以将其移至后线backup.sh
?
答案1
添加支票是个好主意:
if [[ -d ~/backup/$oldday ]]; then
rm -rf "$HOME/backup/$oldday"
fi
另外,在 bash 中正确使用单引号或双引号也很重要。特别是在不使用引号时,包含空格的目录名称可能会导致问题。
更新:我假设OP想要使用bash。
答案2
您的代码中的编码实践存在一些问题。
- 您需要检查这些命令是否成功,尤其是当下一个命令取决于上一个命令的成功时。
- 在列表上下文中保留不带引号的变量是要求 shell 拆分它并对其执行文件名生成,您没有理由在这里这样做。
现在来说rm -r
,它的意思是删除该目录及其所有内容。这样做时它不会遵循符号链接。即使/home/fauna/backup/$oldday
是符号链接,也仅删除该符号链接。这可能就是您想要的。如果你这样做rm -r "/home/fauna/backup/$oldday/"
(带有尾随/
),情况会有所不同。
但是,如果没有-f
,这意味着如果 stdin 是终端,系统可能会提示您删除不可写文件。因此,如果它是一个无人值守的脚本,您可能应该添加它。同样-f
,rm
如果目录随后仍然存在,则仅报告失败。
#!/bin/sh -
day=$(date +%m%d%y) || exit
oldday=$(date -d "-4 days" +%m%d%y) || exit
# date is very unlikely to fail, but if it does, it would have dramatic consequences
# shouldn't access to those directories be restricted (if it hasn't been
# restricted already some levels above)?
# umask 077
mkdir -p "/home/fauna/backup/$day" || exit
# with -p, mkdir would only fail if the directory is not there after that call.
# It may not be what you want though. You may want mkdir to fail if the
# directory already existed in which case you'd want to omit the -p.
cp /home/fauna/backup/backup.sh "/home/fauna/backup/$day" || exit
cd "/home/fauna/backup/$day" || exit
./backup.sh || exit
# only delete the old one if the new one succeeds.
rm -rf "/home/fauna/backup/$oldday"
请注意,这里由于我们要添加|| exit
到每个命令,因此我们也可以使用set -e
这导致 shell 在任何命令出现任何错误时退出,但我更喜欢它,|| exit
因为它明确表明您已经考虑了错误处理(并且set -e
已经太多的陷阱无法可靠地使用(但不是在这个简单的情况下))。