我想获取当前目录下所有文件的 MIME 类型。为什么这不起作用?我已经在 OSX 或 Linux 上测试了 bash。 “file”抱怨它找不到该文件,但如果我使用完全相同的路径运行它,它就可以工作。
$ find . -type f | xargs -n 1 -I FILE echo $(file --mime-type -b FILE)
ERROR: cannot open './foo.txt' (No such file or directory)
...
$ file --mime-type -b ./foo.txt
text/plain
当然,在现实世界中,我不只是“回显”响应,我需要在另一个命令中使用 MIME 类型字符串。
这是我能解决的最简单的问题。我想我不明白有关xargs
文件名替换的事情?
答案1
命令替换$(file --mime-type -b FILE)
是由 shell 在传递给 之前执行的xargs
,这就是为什么您没有看到您需要的内容。引用并通过 xargs$(file --mime-type -b FILE)
传递它bash -c
find . -type f | xargs -n 1 -I FILE bash -c 'echo $(file --mime-type -b FILE)'
答案2
这里没有必要利用xargs
。只需使用 的find
开关即可-exec
。
$ find . -type f -exec file --mime-type -- {} +
例子
默认file
输出
$ find 8* -type f -exec file --mime-type -- {} + | tail -5
89999/sample10.txt: text/plain
89999/sample2.txt: text/plain
89999/sample4.txt: text/plain
89999/sample6.txt: text/plain
89999/sample9.txt: text/plain
file -b
输出
$ find 8* -type f -exec file --mime-type -b -- {} + | head -5
application/x-empty
text/x-perl
text/plain
text/plain
text/plain
备择方案
这仅供参考,但还有另一个命令,称为mimetype
,您也可以使用它来执行与 相同的操作file --mimetype
。此命令是 Fedora 上此软件包的一部分perl-File-MimeInfo
,其工作原理类似:
$ find 8* -type f -exec mimetype -- {} + | tail -5
89999/sample10.txt: text/plain
89999/sample2.txt: text/plain
89999/sample4.txt: text/plain
89999/sample6.txt: text/plain
89999/sample9.txt: text/plain
更详细的执行
鉴于您询问“不仅仅是 echo..”,并且由于您正在尝试使用,xargs
我将得出结论,您认为您需要使用xargs
.
但如果您正在使用find
,这通常不是最好的方法。您可以改为使用find
,然后在find
的-exec
switch 中调用 shell 并在此处执行更复杂的操作,而不是尝试xargs
以更复杂的方式执行此操作。
$ find . -type f -exec sh -c '
cmd1;
cmd2;
file --mime-type -b "$@";
cmd3;
cmd4;
' sh {} \;
笔记:我已经从使用+
传递多个参数的终止符切换为file --mime-type ...
一次\;
传递一个参数。
例子
$ find 8* -type f -exec sh -c '
echo -n "mime-type: ";
file --mime-type -b "$@"
' sh {} \; |& tail -10
mime-type: text/plain
mime-type: text/plain
mime-type: text/plain
mime-type: text/plain
mime-type: text/x-shellscript
mime-type: text/plain
mime-type: text/plain
mime-type: text/plain
mime-type: text/plain
mime-type: text/plain
答案3
您的问题与外壳扩展有关。 $() 在作为参数传递之前会被扩展。如果您想按原样对待它,请单引号它并为其调用 shell。
另外,如果您处理文件名,请养成使用 print0 和 0 的习惯,因为忽略它们会给您带来包含空格字符的文件名的问题。
例子:
find . -type f -print0 | xargs -0 -n 1 -I FILE bash -c 'echo $(file --mime-type -b FILE)'
在您的情况下,这可以简化为:
find . -type f -print0 | xargs -0 -n 1 file --mime-type -b
附加评论:为找到的所有文件调用程序(无论是“xargs -n 1”还是 find+exec)可能是真正的性能瓶颈。如果您的目录包含数千个文件,那么您将生成数千个进程。