如何将“find”的结果作为文件列表传递?

如何将“find”的结果作为文件列表传递?

情况是,我有一个 MP3 播放器mpg321,它接受文件列表作为参数。我将音乐保存在名为“music”的目录中,其中还有一些目录。我只想玩所有这些,所以我运行程序

mpg321 $(find /music -iname "*\.mp3")

。问题是,某些文件名中含有空格,程序将这些名称分成更小的部分并抱怨丢失文件。将结果括find在引号中

mpg321 "$(find /music -iname "*\.mp3")"

没有帮助,因为所有都会变成一个大“文件名”,这显然是找不到的。

那我该怎么办呢?如果这很重要,我正在使用,但很快bash就会切换到。zsh

答案1

尝试结合使用 find's-print0或option ,如下所示:-printfxargs

find /music -iname "*\.mp3" -print0 | xargs -0 mpg321

这是如何工作的解释为find 的手册页:

-打印0

真的;在标准输出上打印完整的文件名,后跟一个空字符(而不是 -print 使用的换行符)。这允许处理查找输出的程序正确解释包含换行符或其他类型空格的文件名。该选项对应于 xargs 的 -0 选项。

答案2

find /music -iname "*\.mp3" -exec mpg123 {} +

通过 GNU find,您还可以使用-print0xargs -0,但是学习另一种工具没有什么意义。该-exec ... {} +语法很少被提及,因为 Linux 晚于 获得它-print0,但现在没有理由不使用它。

使用 zsh 或 bash 4,这要简单得多:

mpg123 **/*.[Mm][Pp]3

仅在 zsh 中,您可以使(部分)模式不区分大小写:

mpg123 (#i)**/*.mp3

答案3

我认为史蒂文的解决方案最好,但另一种方法是使用 xargs-I标志,它允许您指定一个字符串,然后在命令中用参数替换该字符串(而不是仅将参数附加到命令末尾)。您可以使用它来引用参数:

find /music -iname "*\.mp3" | xargs -0 -Ifoo mpg321 "foo"

答案4

另一种方法是转义文件名中出现的所有特殊字符。例如:

find /music -iname "*\.mp3" | sed 's!\([] \*\$\/&[]\)!\\\1!g' | xargs mpg321

这基本上会将正确转义的文件名传递给 xargs 来执行,并且不会有任何问题。

相关内容