我在 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