Bash :将通配符作为 shell 脚本的参数并能够扩展它

Bash : Taking a wildcard as argument of a shell script and being able to expand it

我遇到了一个乍一看很容易的具体问题。

如果我在 bash shell 上键入对应于不同文件的通配符:

$ myfile=probe_*.txt

并在 :

之后执行
$ echo $myfile

我得到了与通配符匹配的所有文件的列表,即:

$ probe_GCph.txt probe_GCsp.txt probe_GCsp_WL_GCph.txt probe_GCsp_XC.txt probe_GCsp_XC_WL_GCph.txt probe_WL.tx

但是现在,我想把通配符probe_*.txt作为参数</code>变成一个函数。</p> <p>目前,如果我在 bash 函数中执行:</p> <pre><code>function multiple_files { myfile= echo echo echo $myfile }

然后,在下面的执行:

$ multiple_files . $myfile dir/

然后我只得到第一个文件名 probe_GCph.txt,它是在 bash 函数的定义中为第三个 echo (echo $myfile) 打印的。

如何将文件的通配符名称作为参数(此处为 $2)传递,然后能够将其展开以列出 bash 函数中对应的所有文件名?

仅考虑第一个扩展文件 probe_GCph.txt 的参数 $2 与不扩展它而将通配符作为参数 $2 传递之间似乎存在冲突。

如何规避这个问题?

双引号避免扩展 shell glob,但仍允许 shell 变量替换。值得注意的是,单引号既可以防止 glob(或类似扩展的通配符)也可以防止变量插值。

长话短说:

这样调用你的函数:

multiple_files . "$myfile" dir/

要在函数内部传递通配符,您需要转义特殊字符或在引号中包含通配符序列。

$ ls
f1  f2  f3

$ function multiple_files { myfile=; echo ; echo ; echo $myfile;}
$ multiple_files '*' f\*
f1 f2 f3
f1 f2 f3
f1 f2 f3

如果您不转义通配符,它​​会在调用函数之前展开

$ multiple_files f*
f1
f2
f2

要在函数内打印通配符,您还需要在引号中包含变量。 eval 也有一些技巧:

$ function multiple_files { myfile=; echo ; eval echo ""; echo ""; echo "$myfile"; eval echo "$myfile";}
$ multiple_files '*' f\*
f1 f2 f3
f1 f2 f3
f*
f*
f1 f2 f3

编写您的函数以接受多个参数而不是一个。这就是大多数其他工具的工作方式(cp/mv/ls/grep/sed 仅举几例):

multiple_files() {
  first=""
  last="${@: -1}"
  files=( "${@:2:$#-2}" )

  echo "The first thing was $first"
  echo "The last  thing was $last"
  for file in "${files[@]}"
  do
    echo "One of the files is $file"
  done
}

multiple_files . probe_*.txt dir/

这导致:

The first thing was .
The last  thing was dir/
One of the files is probe_GCph.txt
One of the files is probe_GCsp.txt
One of the files is probe_GCsp_WL_GCph.txt
One of the files is probe_GCsp_XC.txt

如果您确实需要模式本身,或者如果您想接受多个模式并将它们分开,您可能需要按照其他答案中的描述引用 glob。