参数扩展中的通配符

参数扩展中的通配符

我正在尝试选择作为参数传递的一组目录中的文件,其中包含以下内容:

${@/%/*}

然而,这并不理想,因为带有空格的路径将被破坏,并且引用参数扩展将依次停止文件名扩展。能否有一个满意的解决方案?

PS:我知道你应该用来find -maxdepth执行此操作,但我很好奇为什么将参数扩展与通配符混合起来看起来如此困难。

答案1

你总是可以这样做:

IFS=              # don't split
files=(${@/%/*})  # use split+glob upon expansion with split disabled

但是,如果"$@"包含通配符,它​​们将被如此解释。此外,对于每个不匹配的 glob,您最终都会得到未展开的模式。

您可以使用循环和nullglob选项来解决这些问题:

shopt -s nullglob
files=()
for arg do files+=("$arg"*); done

或者您可以使用zsh代替bash并使用:

files=($^argv*(N))

$^array打开rcexpandparam的一次扩展选项$array。在rcshell 中(shell 中也是如此fish),$array*where$array包含两个元素ab扩展为a*, b*,所以这里就像 do files=($argv[1]*(N) $argv[2]*(N)...)$argv[1]与 相同$1,只是更冗长)。(N)它本身是一个 glob 限定符,用于打开nullglob该 glob 的行为。

fishshell 中,那就是:

set files $argv*

as在参数中fish启用nullglob类似行为,set并与 类似地扩展数组rc。但请注意,语法与more thanfish的语法完全不同。bashzsh

请注意,这些旨在按照您的意愿扩展"$1"*, ... 全局。如果您实际上的意思是... globs,作为您的"$2"*${@/%/*}"$1"/*"%2"/*作为参数传递的一组目录中的文件建议,您需要 在上面的代码片段中使用${@/%/\/*}, , "$arg"/*, $^argv/*(N)$argv*

答案2

用反斜杠+字符替换其他通配符。用反斜杠+字符替换空白字符或(更稳健)设置IFS为空字符串。请记住首先转义反斜杠,这样您就不会最终重新转义先前转义步骤产生的反斜杠。但如果没有什么可转义的,就不要转义任何内容,因为反斜杠只有在存在通配符时才是特殊的。

nullglob如果没有匹配项,则设置该选项以获取空列表,而不是未展开的模式。在函数中执行此操作,并安排将更改保留到 shell 选项和IFS本地。

最低限度的测试:

function set_patterns {
  typeset restore_shopt=$(shopt -p nullglob)
  shopt -s nullglob
  typeset IFS=
  typeset x
  patterns=()
  for x; do
    if [[ "$x" == *[*?[]* ]]; then
      x="${x//\\/\\\\}"
      x="${x//\*/\\*}"
      x="${x//\?/\\?}"
      x="${x//\[/\\[}"
    fi
    x="${x//%/*}"
    patterns+=($x)
  done
  eval "$restore_shopt"
}

相关内容