gpt4 book ai didi

shell - 动态通配

转载 作者:行者123 更新时间:2023-12-03 23:18:55 26 4
gpt4 key购买 nike

set +f; rm *; touch a; for i in *; do touch b; echo $i; done

在我尝试过的所有 shell(dash、ksh、zsh、bash)中,上面的代码片段只输出“a”。在 C 中实现相同,(在 readdir 上创建文件的 opendir/loop)也只输出“a”。但是,如果目录包含足够的文件(~4096),C 实现通常也会输出“b”。 (即,readdir 返回在 opendir 之后创建的文件的结果)。我在 shell 标准中看不到任何指示 shell 在这种情况下应该如何响应的内容。标准兼容的 shell 是否可以进入在 glob 之后创建的文件的循环?这是一个非常理想的特性,因为这意味着 shell 在执行任何操作之前不会将整个 glob 读入内存。在预期目录包含许多文件的情况下,通常需要几秒钟才能将 glob 读入内存,这是浪费时间。

是否有任何 shell 实现在进入循环之前不将整个 glob 读入内存?

最佳答案

没有。 glob 扩展到的上下文本质上与普通命令扩展上下文相同,其中所有扩展都被处理,结果单词以不可变的方式保存以供迭代。 for-in 循环不可能有惰性迭代器。当然,扩展可能会产生副作用并与 glob 混合,因此必须热切地评估它们。这就是为什么 find -exec [+;] 在可能同时执行某些操作时仍然比 globstar 更经常被推荐的原因。

关于这个 4096 问题,我真的无话可说。我认为这两者真的没有可比性。 Shell for..in 只是扩展单词并迭代它们。

一个相关的常见问题解答是您是否可以执行诸如预读到下一个要分配的值之类的操作。据我所知,没有任何类似于 bourne 的 shell 可以提供对单词列表的任何额外访问权限。你必须为此使用数组。基本上 for..in 的所有限制都可以通过数组来克服。

这是我为 Bash 编写的一个有趣的惰性 coproc 生成器。这没什么用。

coproc x { while :; do find . -type f -maxdepth 1 -exec sh -c 'read; echo "$1"' -- {} \;; done; };

while :; do
echo 1 >&"${x[1]}"
read -ru "${x[0]}" file
echo "$file"
sleep 1
done

还有一个与问题无关的 for..in 花絮 -- 在 ksh93 和 Bash 的 git devel 分支中,可以使用“控制变量”以一种有趣的方式。

function f {
nameref x # Chet may decide not to emulate the typeset -n aliases

for x; do
x=hi
done
}

typeset -a arr
f 'arr['{0..3}']'
typeset -p arr # arr=(hi hi hi hi)

每次迭代都会将给定对象的引用分配给 x。当然,在 ksh 中,它可以是任意复杂数据类型。我想这可能会被滥用以某种方式模拟懒惰。不幸的是,这种模式在 mksh 中似乎不起作用。

编辑 自从写这篇文章后我就忘记了,我发现很多 shell 实际上都在优化 for x 语法。我假设至少 for x in 是写时复制的,并且只有在 shiftset 被使用时才会复制位置参数循环。

关于shell - 动态通配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12896563/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com