![大型输出重定向中的 Bash 脚本顺序混合](https://linux22.com/image/123924/%E5%A4%A7%E5%9E%8B%E8%BE%93%E5%87%BA%E9%87%8D%E5%AE%9A%E5%90%91%E4%B8%AD%E7%9A%84%20Bash%20%E8%84%9A%E6%9C%AC%E9%A1%BA%E5%BA%8F%E6%B7%B7%E5%90%88.png)
我有一个脚本,它运行数据库查询并将结果重定向到 csv 文件,在使用 sftp 上传它之后,该文件将被删除,如下所示:
FileName=` echo "report_$StartDate:$StopDate.csv" | sed 's/\ /_/g'`
$DatabaseCommand "$Query" -f CSV | sed 's/"//g' > "$ReportDir/$FileName"
expect<<EOD
set timeout 3600
spawn sftp $USER@$HOST
expect "password:"
send "$PASSWORD\r"
expect "sftp>"
send "put $ReportDir/$FileName\r"
expect "sftp>"
send "bye\r"
EOD
rm -rf $ReportDir/$FileName
我知道最后一行应该更改为rm -f
,但我想知道 bash 是否可以在 FileName 行中混合并能够运行以下命令:
rm -rf $ReportDir/
答案1
使用这样的命令,您可能希望防止变量为空,无论这种情况如何发生:
$ cat foo.sh
#!/bin/bash
ReportDir=/somepath
FileNam=$(echo ...) # oops, a typo
# ...
rm -rf -- "${ReportDir:?}/${FileName:?}"
$ bash -x foo.sh
+ ReportDir=/somepath
++ echo ...
+ FileNam=...
foo.sh: line 5: FileName: parameter null or not set
如果为空或未设置,则扩展${parameter:?message}
会退出并出现错误。parameter
默认消息通常就可以了,所以我没有在上面的代码中给出一条消息。
或者,只需手动检查,但这很冗长并且仍然容易出现拼写错误:
if [ -z "$FileName" ] ; then
echo "FileName is empty!" >&2
exit 1
fi
rm -rf -- "$ReportDir/$FileName"
答案2
由于StartDate
、StopDate
和ReportDir
未在您向我们展示的脚本中设置,因此我假设这不是整个脚本。所以:
$ cat foo.sh
ReportDir=foo
# commands from what you have shown, omitting `expect` and db command
FileName=` echo "report_$StartDate:$StopDate.csv" | sed 's/\ /_/g'`
rm -rf $ReportDir/$FileName
$ bash -ux foo.sh
+ ReportDir=foo
foo.sh: line 2: StartDate: unbound variable
++ sed 's/\ /_/g'
+ FileName=
+ rm -rf foo/
显然它已经膨胀FileName
到什么都没有了,然后就跑了rm -rf foo/
。
答案3
考虑使用sshpass反而。
SSHPass 是一个小型实用程序,允许您在不使用提示符的情况下提供 ssh 密码。这对于脚本编写非常有帮助。 SSHPass 不适合在多用户环境中使用。如果您在开发机器上使用 SSHPass,它不会做任何坏事。