通配符*在bash脚本中的行为不正常

问题描述 投票:0回答:1

我有一个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文件)。

为什么我的通配符在脚本中不能像在终端上依次按顺序分别运行时那样起作用,我应该怎么做才能使通配符在脚本中正常工作?

bash unix stdout glob
1个回答
2
投票

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

[在下面,我们定义一个assert_only_one函数,当从glob分配的数组中包含的元素少于或多于一个时,该脚本将停止脚本。因此,我们能够编写更清楚,明确地描述我们所需行为的代码。

#!/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
© www.soinside.com 2019 - 2024. All rights reserved.