无需通配即可扩展 shell 变量

Ste*_*ett 3 bash wildcards test variable-substitution

我想检查输入字符串是否指的是文件名 -而不是*.txt.

这不起作用:

if [ -f "$1" ];
Run Code Online (Sandbox Code Playgroud)

因为$1被扩展到*.txt,它被扩展到,比如说foo.txt bar.txt,它被传递到test -f

除了明确检查通配符之外,是否有一种通用的方法来执行 shell 替换,然后防止任何通配符?

Sté*_*las 5

不,引用时不会扩展globs ,因此:

set -- '*.txt'
[ -f "$1" ]
Run Code Online (Sandbox Code Playgroud)

将检查*.txt当前目录中调用的文件是常规文件还是常规文件的符号链接。

[ -f $1 ]
Run Code Online (Sandbox Code Playgroud)

将是一个问题($1会进行分词(这里不对 的默认值进行任何操作$IFS)和文件名生成)。

如果您想检查是否有带.txt扩展名的常规文件,您需要一个循环或 usefindzshglob 限定符。

set -- *.txt
for f do
  if [ -f "$f" ]; then
    echo "there is at least one regular file with a .txt extension here"
  fi
done
Run Code Online (Sandbox Code Playgroud)

或者,如果在以下位置找到模式$1

IFS= # disable the globbing part of the split+glob operator
set -- $1
for f do... # as above
Run Code Online (Sandbox Code Playgroud)

zsh

files=(*.txt(N-.))
echo "$#files regular files with a .txt extension here"
Run Code Online (Sandbox Code Playgroud)

find

find -L . ! -name . -prune ! -name '.*' -name '*.txt' -type f | grep -q . &&
  echo there are regular .txt files in here
Run Code Online (Sandbox Code Playgroud)

  • @SteveBennett,如果您的脚本被称为`my-script *.txt`,那么调用shell 将在调用脚本之前扩展该`*.txt`。`my-script` 将收到 `$1` 中的 `bar.txt` 和 `$2` 中的 `foo.txt`... 你不需要在你的脚本中扩展通配符。 (2认同)
  • 没办法。就像无法判断脚本是被称为`my-script $files` 还是`my-script "${files[@]}"` 或`my-script $(ls)` 一样。 (2认同)