重定向到全局文件名失败

重定向到全局文件名失败

我在 Ubuntu 16.04 (xenial) 中使用 Bash 4.3.48(1) 和 LEMP 堆栈。

我尝试以php.ini与版本无关的方式使用printf.

1)与版本无关的操作失败:

printf "[PHP]\n post_max_size = 200M\n upload_max_filesize = 200M\n cgi.fix_pathinfo = 0" > /etc/php/*/fpm/zz_overrides.ini

给出以下错误:

bash: /etc/php/*/zz_overrides.ini: 没有这样的文件或目录

2)版本 gnostic 操作成功:

printf "[PHP]\n post_max_size = 200M\n upload_max_filesize = 200M\n cgi.fix_pathinfo = 0" > /etc/php/7.0/fpm/zz_overrides.ini

*正如您所看到的,除了vs之外,两者基本相同7.0

  • 我在 中没有找到有关此(正则表达式?)问题的线索man printf
  • 我在谷歌中搜索,没有发现任何关于“允许在 printf 中使用正则表达式”的内容。

为什么版本无关操作失败,是否有任何绕过?

编辑:如果可能的话,对我来说最重要的是使用一行操作。

答案1

重定向中模式匹配的行为在 shell 之间似乎有所不同。在我的系统上,dash 和 ksh93 不会扩展模式,因此您会得到一个带有文字的文件名*。 Bash 会扩展它(1),但前提是该模式与一个文件匹配。如果有更多匹配的文件名,它会抱怨。 Zsh 的工作方式就像您给出了多个重定向一样,它将输出重定向到全部匹配文件。

(1) 非交互式且处于 POSIX 模式时除外

如果您希望输出到所有匹配的文件,您可以使用tee

echo ... | tee /path/*/file > /dev/null

如果您希望它只访问一个文件,问题就在于决定使用哪一个。如果您想检查是否只有一个文件与该模式匹配,请展开整个列表并对它们进行计数。

在 bash/ksh 中:

names=(/path/*/file)
if [ "${#names[@]}" -gt 1 ] ; then
    echo "there's more than one"
else
    echo "there's only one: ${names[0]}"
fi

在标准 shell 中,set位置参数用于$#计数。


当然,如果该模式与任何文件都不匹配,则它会保持原样,并且由于 glob 位于中间,因此结果指向一个不存在的目录。这与尝试在存在之前创建/path/to/file,是一样的/path/to,只是在这里我们/path/*用星号代替了。

为了解决这个问题,您必须扩展不带文件名的目录名,然后将文件名附加到所有目录。这有点丑啊……

dirs=(/path/*)
files=( "${dirs[@]/%/\/file}" )

然后我们可以使用该数组:

echo ... | tee "${files[@]}" > /dev/null

或者我们可以采取简单的方法并循环文件名模式。在更一般的情况下,这有点不能令人满意,因为它需要为每个输出文件运行一次主命令,或者使用临时文件来保存输出。

for dir in /path/* ; do
    echo ... > "$dir/file"
done 

相关内容