为什么不是'cat foo.txt |如果没有找到文件,读取`失败?

时间:2015-02-03 21:10:00

标签: bash

我使用此循环来遍历文件,或者,如果没有文件,则读取stdin:

#!/bin/bash
set -e
cat "$@" | while read arr ; do
    echo "Got this line ${arr}"
done

问题是如果文件不存在,则不会出错。

您可以在此处查看完整示例: https://github.com/StackExchange/blackbox/blob/master/tools/mk_rpm_fpmdir

如果找不到任何文件,

cat会返回错误代码1。但是,该错误不会导致程序停止。

如果找不到文件,我如何迭代$@并失败?

2 个答案:

答案 0 :(得分:3)

有几种可用选项。一个是简单地抛弃cat,因此没有管道(具有避免子shell使用的有利副作用,因此允许更改shell状态 - 变量集等等 - 持续超出内部循环) :

set -e
for f; do # in "$@" is implicit
  while read -r -a arr; do
    printf 'Got line: '
    printf '%q ' "${arr[@]}"
    printf '\n'
  done <"$f"
done

上述内容也是以完全保留数组读取方式打印内容的方式,并明确打印其内容(区分包含两个元素foo bar baz的数组包含三个元素foo bar baz)。


另一种方法是设置pipefail,如果管道的任何组件返回非零退出状态(包括cat),将导致管道被视为失败:

set -e
set -o pipefail
cat "$@" | while IFS= read -r; do
  printf 'Got line: %q\n' "$REPLY"
done

这可以通过覆盖默认行为来实现,只有管道的右侧才能考虑命令的整体退出状态。

答案 1 :(得分:1)

for f in "${@}"; do
    test -f "${f}" || exit # fail if file doesn't exist
    cat "${f}" | awk '{print "Got this line" $0}'
done