我编写了一个脚本来备份用户使用脚本输入的第一个参数:
# Sample data
df <- read.table(text =
"Plant Branch Pod_B Flow_Miss Pod_A Flow_T Trt Dmg
1 1 1.00 0 16 20 36.0 Early 1
2 1 2.00 0 1 17 18.0 Early 1
3 1 3.00 0 0 17 17.0 Early 1
4 1 4.00 0 3 14 17.0 Early 1
5 1 5.00 5 2 4 11.0 Early 1
6 1 6.00 0 3 7 10.0 Early 1
7 1 7.00 0 4 6 10.0 Early 1
8 1 8.00 0 13 6 19.0 Early 1
9 1 9.00 0 2 7 9.00 Early 1
10 1 10.0 0 2 3 5.00 Early 1
11 1 10.0 0 2 3 20.00 Late 1", header = T)
我想从脚本中得到的结果是
但是当我尝试输入参数时脚本没有运行。脚本出了什么问题?
答案 0 :(得分:2)
您的脚本的备份部分似乎运行良好,但不是您检查$1
不为空的部分。
首先,您需要$1
周围的引号,以防止它消耗任何东西。如果没有引号,shell会将其视为
if [ -eq 0 ]
并抛出错误。
其次,最好使用-z
运算符来测试变量是否存在:
if [ -z "$1" ]
现在你的脚本应该按预期工作了
答案 1 :(得分:1)
我看到了几个问题:
if [ -z "$1" ]
检查缺失/空白参数。"$1"
所示。您在测试中是否存在$file
,而不是tar
命令。有些地方可以放弃双引号,但规则很复杂; 总是双引号更容易。除了检查是否已通过$1
之外,我还建议检查它是否与实际存在的目录(或可能是文件)相对应。使用类似的东西:
if [ -z "$1" ]; then
echo "$0: We need first argument to backup" >&2
elif [ ! -d "$1" ]; then
echo "$0: backup source $1 not found or is not a directory" >&2
BTW,请注意错误消息如何以$0
(脚本运行的名称)开头,并指向错误输出(>&2
部分)?这些都是错误消息的标准约定。
$1/$(date +"_%Y-%m-%d").tar.gz
,将其存储在file
变量中,测试是否存在该名称的某些内容,然后计算创建备份文件时再次。没有理由这样做;只需再次使用file
变量。它让我烦恼的部分原因在于它违反了DRY(“不要重复自己”)的原则,部分原因是如果你改变了命名约定,你必须在两个地方一致地改变它,否则脚本将无法工作,部分原因是因为原则上脚本可能会在午夜运行,第一次计算会得到一天而第二次会得到不同的一天。说到命名约定,存储备份文件的方式存在问题。如果您将其放在正在备份的目录中,那么第一天您将获得包含该目录的先前内容的.tar.gz文件。第二天,您将获得包含常规内容和第一个备份文件的文件。因此,第二天的备份将大约两倍。第三天的备份将包含常规内容,以及前两个备份文件,因此它将是原来的四倍。第四天将是8倍,然后是16倍,然后是32倍等等。
您需要将备份文件存储在外部正在备份的目录中,或者将--exclude="*.tar.gz"
之类的内容添加到tar
的参数中。 --exclude
选项的缺点是它可能会从备份中排除其他.tar.gz文件,所以我真的推荐第一个选项。如果您遵循我的建议,在任何地方使用"$file"
而不是重新计算名称,您只需在一个地方进行更改即可更改备份的位置。
最后一点:通过shellcheck.net运行您的脚本。在你发现困难之前,它会指出很多常见错误和不良做法。
这是脚本的更正版本(将备份存储在目录中,不包括.tar.gz文件;我再推荐其他选项):
#!/bin/bash
file="$1/$(date +"_%Y-%m-%d").tar.gz"
if [ -z "$1" ]; then
echo "$0: We need first argument to backup" >&2
elif [ ! -d "$1" ]; then
echo "$0: backup source $1 not found or is not a directory" >&2
elif [ -e "$file" ]; then
echo "$0: A backup already exists for today" >&2
else
tar --exclude="*.tar.gz" -zcvf "$file" "$1"
fi