Bash 函数参数中的通配符问题

Issue with wildcards into arguments of a Bash function

从下面link,我尝试用下面的方案比较了一组源文件(这里是fortran90 = *.f90)

为了做到这一点和查看源码有什么不同,我已经放入我的 ~/.bashrc :

function diffm { for file in ""/""; do diff -qs "$file" ""/"${file##*/}"; done ;}

但不幸的是,如果我在参数 </code> 的当前目录中,即执行:</p> <pre><code>$ diffm . '*.f90' ../../dir2

结果是:impossible to access to './*.f90'。但是,来源 *.f90 存在,但不考虑通配符。

肯定是我函数参数上的双引号问题 (</code>、<code></code>)?</p> <p>更一般地说,此功能效果不佳。</p> <p>如何修改此函数以使其在所有情况下都能正常工作,即使在当前目录“<code>.”中第一个参数 </code> 或第三个 <code>?

如果我明白你想做什么,这应该行得通

diffm () {
    dir=""; shift
    for file in "$@"; do
        filename=$(basename "$file")
        diff -qs "$file" "$dir/$filename"
    done
}

用法

diffm ../../dir2 ./*.f90

文件名生成不在引号内。因此,您将文字字符串 *.f90 传递给函数,并且该字符串也按字面意义在那里使用。如果您确定您的目录中只有一个 f90 文件,请不要使用引号并写

diffm . *.f90 ../../dir2

如果文件名嵌入了 space,事情就会变得很难看(顺便说一句,这是我更喜欢 Zsh 而不是 bash 的原因之一——在 Zsh 中你不必关心这个).要处理这种情况,您可以执行

myfile=*.f90
diffm . "$myfile" ../../dir2

但迟早,您会被这样一个事实所困扰,即无论出于何种原因,您拥有多个 f90 文件,并且您的策略将会失败。因此,更好的解决方案是使用循环,这也适用于只有一个文件的边界情况:

iterating=0
for myfile in *.f90
do
    if ((iterating == 0))
    then
      ((iterating+=1))
      diffm . "$myfile" ../../dir2
    elif [[ ! -f $myfile ]]
    then
      echo "No files matching $myfile in this directory"
    else
      echo "ERROR: More than one f90-file. Don't know which one to diff" 1>&2
    fi
done

elif 部分只关心您没有任何 f90 文件的情况。在这种情况下,循环体被执行一次,myfile包含通配符模式。