linux - 为什么“mpv $(ls video\ *)”与“mpv video\ *”不一样?(请帮助 noobie 使用 shell)
问题描述
所以,问题是 - 我有一个文件列表,我想将它们发送到一个程序中,所以它可以在同一个过程中处理这个列表。我的意思是,例如我有一堆视频文件,我想用 mpv 播放,但我需要将它们传递到我可以用ls video\ * | sort -k2
. 每个文件的名称看起来像video [number] - [title].mp4
. 我想按[number]
列对它们进行排序,所以我调用ls
和sort
程序,因为我的外壳(zsh)不能自己做这样的事情(我认为)。
所以我输入ls video\ * | sort -k2
了它,它给了我一个我想要的排序列表。但是当我试图将它传递给 mpv 时mpv $(ls video\ * | sort -k2)
,由于某种原因,mpv 不会逐行读取文件名,而是从一个空间到另一个空间读取它们(我的意思是,这不是 mpv 的问题,它是给 mpv 的 shell此类参数由空格而不是行分隔)。
我尝试用引号括住每一行,尝试创建一个单行列表,同时尝试两者,但如果有效,则没有。Shell 总是按空格分隔文件名,它忽略换行符或引号。这都是因为空间,不是吗?
解决方案
为什么“mpv $(ls video\ *)”和“mpv video\ *”不一样?
因为命令替换的结果会进行分词,而文件名扩展的结果不会,因为分词发生在 文件名扩展之前(请参阅shell 扩展)。
分词是一种神奇的东西,当参数不被引用时,它会被用于使用空格的参数。这意味着,对于一个只打印参数计数的函数- 当未f() { echo $#; }
使用时,该函数将接收 6 个参数 -扩展的结果被吐在空格上。var="a b c variable with spaces"; f $var
$var
f
$var
当命令替换的结果不被引用时,它会进行分词。这意味着在f $(echo a b c)
函数f
中将接收 3 个参数。
因为您的文件中有一个空格video\ *
- 当您传递一个ls
输出带有空格的字符串的命令的未引用结果时,它将被吐在空格上。因此video
,其余的将是单独的论点。
不要解析 ls。ls
用于在 shell 中进行漂亮的打印 - 仅此而已。大多数情况很容易转换为,find -exec
或者find | xargs
例如您想要:find . -maxdepth 1 -type f -name 'video *' | sort -k2 | xargs -d '\n' mpv
或者使用零终止流更好:find . -maxdepth 1 -type f -name 'video *' -print0 | sort -z -k2 | xargs -0 mpv
.
这都是因为空间,不是吗?
是的。
推荐阅读
- kotlin - 获取 Ktor http 请求的内容
- vue.js - Vue,更改本机事件不起作用,输入本机确实
- c# - C# eBay OAuth 合规性 API 身份验证问题
- .net-core - 粒度域事件
- java - 如何在 Selenium Webdriver POM 模型中打印 WebElement 变量名?
- android - 无法在仪表板活动中的 supportActionbar 上实现后退箭头
- c# - asp.net mvc 应用程序中常量值的单独文件
- python - 通过 request 方法从另一个 wsgi 应用程序中执行一个 wsgi 应用程序并存储 html 数据
- c# - 将大文件读入字节数组并将其编码为 ToBase64String
- batch-file - 从一个列表中搜索文件名并将它们替换为 BATCH 中的另一个列表