如果未提供文件名,如何将文本重定向到文件或标准输出

问题描述

我正在编写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") }); grepcatcut等):>

paste

这样,不需要额外的参数来指定输出文件。