bash - 引用命令替换的正确方法
问题描述
我有一个简单的 bash 脚本,它只输出作为位置参数提供给脚本的文件名:
#!/usr/bin/env bash
for file; do
echo "$file"
done
假设我有带空格的文件(例如“f 1”和“f 2”)。我可以使用通配符调用脚本并获得预期的输出:
$ ./script f*
> f 1
> f 2
但是如果我使用命令替换它不起作用:
$ ./script $(echo f*)
> f
> 1
> f
> 2
当我的命令替换输出多个带空格的文件名时,如何正确引用?
编辑:我最终想要的是以随机顺序将文件名传递给脚本(这比仅仅回显它们的名称稍微复杂一些),例如:
./script $(ls f* | shuf)
解决方案
使用 GNUshuf
和 Bash 4.3+:
readarray -d '' files < <(shuf --zero-terminated --echo f*)
./script "${files[@]}"
其中--zero-terminated
可以处理任何文件名,并且readarray
还使用空字节作为分隔符。
对于readarray
不支持该-d
选项的旧 Bash:
while IFS= read -r -d '' f; do
files+=("$f")
done < <(shuf --zero-terminated --echo f*)
./script "${files[@]}"
在有很多文件的极端情况下,这可能会遇到命令行长度限制;在这种情况下,
shuf --zero-terminated --echo f*
可以替换为
printf '%s\0' f* | shuf --zero-terminated
向Socowi指出的帽子提示--echo
。
推荐阅读
- c# - 从 json 中丢弃更多外部对象并取内部
- react-native - 使用本机反应的 Applock
- aframe - GLTF 不使用 ar.js 显示
- javascript - 为什么 Fetch POST 请求后 RedirectToAction 不返回 new View()?
- excel - 在破折号 (-) 之后但在数字之前添加前导 0
- android - 无法弄清楚如何生成@TypeParceler
使用类名使用 KotlinPoet 进行注释 - nginx - 意外的阻塞行为
- python-3.x - 创建单个表而不是 create_all 时出错
- flutter - 如何在 Flutter CustomPainter 中使用贝塞尔曲线绘制形状
- c# - WPF MVVM 短时间显示标签文本