问题描述
我正在编写bash脚本,并希望将文件名用户应将其数据写入其中的输入参数之一。但是,如果没有提供文件名,我想将相同的数据输出到stdout。
是否有一种简单的方法来执行此操作,而不用到处都是一堆if语句来尝试检查数据应该去哪里?
谢谢
解决方法
如果仅通过重定向传递exec
,它将更改当前shell实例中文件描述符指向的位置,而不是用另一个进程替换该shell。
您可以使用它有条件地就地重定向标准输出:
#!/usr/bin/env bash
output_file=$1 # set this however you choose
[[ $output_file ]] && exec >"$output_file" # make stdout point to output_file
echo "This is written either to stdout,or to the output file"
对于bash 4.1或更高版本,如果不想覆盖整个程序及其子级的stdout,也可以使用更高级的方法,分配新的文件描述符并使用变量来引用它:
#!/usr/bin/env bash
case $BASH_VERSION in ''|[123].*)|4.0.*) echo "ERROR: Bash 4.1 required" >&2; exit 1;; esac
output_fd=1 # default to stdout
[[ $output_file ]] && exec {output_fd}>"$output_file" # or override w/ named file
echo "This is written to either stdout,or to the output file" >&$output_fd
这两种方法都比一遍又一遍地使用>>"$output_file"
效率更高,因为每次使用重定向操作符时>>"$output_file"
都会重新打开输出文件;而>&$output_fd
重用已经打开的文件描述符,只需要运行fdup()
操作就可以将单个文件复制到插槽1中,从而将输出重定向到该命令。
经过一番尝试后,我发现如果您设置文件名,则将输出重定向到“ / dev / stdout”即可。因此,在脚本的开头只需添加:
FILENAME=$1
if [ $FILENAME = "" ]; then
FILENAME="/dev/stdout"
fi
echo "my data" > $FILENAME
如果给定文件名,则应将数据输出至文件名;如果不给定文件,则应将数据输出至stdout。
,通常,此类脚本使用此简单约定(也由许多* NIX实用程序共享,例如User.updateOne({
_id: req.user._id
},{
$push: {
Playlists: req.body
}
}).then(data => {
res.redirect("/home")
});
,grep
,cat
,cut
等):>
paste
这样,不需要额外的参数来指定输出文件。