【问题标题】:wildcard * not behaving in expected way in bash script通配符 * 在 bash 脚本中未按预期方式运行
【发布时间】:2020-06-10 19:32:40
【问题描述】:

我有一个如下所示的 bash 脚本。我在包含input1.inp 等文件和coords_i.xyzsubmission.sub 等其他文件的目录中运行它,以便对它们进行一些简单的修改:

#!/bin/bash 
sed -i -e '25d' *.inp
echo "*xyz -2 2" >> *.inp
sed -n '3,7p' *_i.xyz >> *.inp
echo "Q -1 0 0 3" >> *.inp
echo "Q +1 0 0 -3" >> *.inp
echo "*" >> *.inp
sed -i -e s/"replace1"/"replace2"/g *.sub
rm *.out

如果我在这个目录中,并且我在终端中单独运行所有命令(在脚本中逐行),一切正常。但是,当我尝试将所有这些命令分组到脚本中时,如上所示,我收到一个错误 - 基本上在 sed -i -e '25d' *.inp 行之后,脚本停止并在我的目录中创建了一个名为 *.inp 的文件。如果我尝试在此之后单独运行echo 命令,它会说该命令不明确(可能是因为存在这个*.inp 文件)。

为什么我的通配符在脚本中的工作方式与我在终端中单独并按顺序运行它们时的工作方式不同,我该怎么做才能使它们在脚本中正常工作?

【问题讨论】:

  • >> *.inp 如何工作?一个文件描述符一次只能打开一个文件(即使你这样做exec > >(tee one.inp two.inp),写入tee 的FIFO 也只有一个描述符)。如果您有 no 匹配文件,则 glob 会扩展为自身(因此您如何获得 *.inp 文件);如果您有 多个 匹配文件,则它会扩展为多个文件,并且不能再用作合法的重定向目标。
  • ...无论如何,我强烈(强烈!)建议只评估一次你的 glob,将结果存储在一个数组中,然后读取数组(或者只读取数组的第一个元素,如果你想断言应该只有一个文件)。

标签: bash unix stdout glob


【解决方案1】:

以这种方式使用通配符是危险的;简单的建议是“不要”。只对它们进行一次评估,然后您可以在尝试使用它们之前检查它们的输出。

在下面,我们定义了一个assert_only_one 函数,当一个数组(从全局分配)包含少于或多于一个元素时,该函数会停止您的脚本。因此,我们能够编写更清晰、更明确地描述我们想要的行为的代码。

#!/usr/bin/env bash

shopt -s nullglob      # Stop *.xyz evaluating to '*.xyz' if no such files exist

assert_only_one() {
  local glob; glob=$1; shift
  case $# in
    0) echo "ERROR: No files matching $glob exist" >&2; exit 1;;
    1) return 0;;
    *) echo "ERROR: More than one file matching $glob exists:" >*2
       printf '  %q\n' "$@" >&2
       exit 1;;
  esac
}

inp_files=( *.inp );   assert_only_one '*.inp' "${inp_files[@]}"
sub_files=( *.sub );   assert_only_one '*.sub' "${sub_files[@]}"
xyz_files=( *_i.xyz )

sed -i -e '25d' "${inp_files[0]}"
{
  echo "*xyz -2 2"
  sed -n '3,7p' "${xyz_files[@]}"
  echo "Q -1 0 0 3"
  echo "Q +1 0 0 -3"
  echo "*"
} >>"${inp_files[0]}"
sed -i -e s/"replace1"/"replace2"/g -- "${sub_files[@]}"
rm -- *.out

【讨论】:

    猜你喜欢
    • 2014-07-02
    • 2018-05-07
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 2018-04-24
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    相关资源
    最近更新 更多