3 ms·
There is another difference that users may care about here. zsh will create a temp file for each here-string in the here-string version, and bash may do too¹.
by JNRowe 3y ago
There is another difference that users may care about here. zsh will create a temp file for each here-string in the here-string version, and bash may do too¹. Whether those files hit a disk is a matter of system configuration, and whether such a disk is magically quick or swirling rust is a different issue too.
[Just noting that the implementation here isn't equivalent for nerdsnipe-ery, not arguing for real attempts at optimisation of simple pipelines.]
¹ Always with older versions, only for large strings with newer versions.
- chrismorgan 3y agoInteresting, didn’t know about that. Hadn’t thought about it too deeply. python <<<'import subprocess; subprocess.run(["ls", "-la", "/proc/self/fd"])' Running under zsh, link 0 -> '/tmp/zshqqjTS0 (deleted)'; under bash, link 0 -> 'pipe:[1509353]'. (I know <(…) is substituted in zsh with /proc/self/fd/… for a fd corresponding to a pipe:[…], and regular | piping makes 0 be a pipe:[…].) I know some common configurations use concrete /tmp. Mine is tmpfs. Thanks for the info! I like sharing these kinds of things because I have found them interesting and expect a few others will too, and people often add to them details I hadn’t known and like to know!
- JNRowe 3y agoFellow shell trivia enthusiast, hi! $ bash -c 'realpath /dev/stdin <<< small' /proc/79631/fd/pipe:[5282632] $ bash -c 'realpath /dev/stdin <<< $(printf "%65536s")' /tmp/sh-thd.yZ2L6p (deleted) You can see the cutover on buffer size from my install of bash 5.2.15. Anything under 64k of here-string will still use a pipe. In case you weren't aware, you can also force a "real" file with zsh process substitution by using =(…)¹. It can be useful when the tool you're using doesn't behave correctly with <(…), if it wishes to seek across it for example. Sadly, =(…) isn't supported in bash [yet?]. ¹ In your case it still wouldn't hit a disk as it is in /tmp, but it at least becomes seekable.