更容易表现为试图用文字描述。
find . -name jo\* -print > list
cat list
#./jo1
#./jo2
#./jo3
# the "file" by reading the list of files from the file "list"
file -f list
#./jo1: ASCII text
#./jo2: ASCII text
#./jo3: ASCII text
#now with process substitution
file -f <(find . -name jo\* -print)
什么都不输出..;(
#repeat with -x
set -x
file -f <(find . -name jo\* -print)
set +x
#shows
+ file -f /dev/fd/63
++ find . -name 'jo*' -print
+ set +x
所以,应该工作。但不是。为什么呢?
修改
请注意 - 流程替换应该在您应该输入文件名的任何地方使用,比方说:
diff <(some command) <(another command)
以上用作
的bashdiff /dev/fd/... /dev/fd/...
也可以在grep
中使用:
grep -f <(command_for_produce_the_patterns) files..
再次,bash
在内部将其用作
grep -f /dev/fd/63 files....
因此,同样的 应该在file
file -f <(command)
答案 0 :(得分:5)
你做得对。这是你file
实现中的一个错误,我可以在我的网站上重现(Debian jessie上的文件5.22)。它期望-f
的参数是可搜索文件,并且在文件不可搜索时不检测错误。这就是为什么它适用于常规文件,而不是管道(这是进程替换用于在两个进程之间传递数据的原因)。
您可以观察strace
:
$ strace file -f <(echo foo)
…
open("/proc/self/fd/13", O_RDONLY) = 3
fstat(3, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
…
read(3, "foo\n", 4096) = 5
…
read(3, "", 4096) = 0
lseek(3, 0, SEEK_SET) = -1 ESPIPE (Illegal seek)
read(3, "", 4096) = 0
close(3) = 0
文件程序打开文件描述符3上的文件名列表并读取它。它试图寻找文件的开头。这会失败,但程序会再次从文件中读取,因为文件位置已经结束,所以不会产生任何数据。因此,文件以文件名的空列表结束。
在源代码中,-f
选项会触发unwrap
函数:
private int
unwrap(struct magic_set *ms, const char *fn)
{
// …
if (strcmp("-", fn) == 0) {
f = stdin;
wid = 1;
} else {
if ((f = fopen(fn, "r")) == NULL) {
(void)fprintf(stderr, "%s: Cannot open `%s' (%s).\n",
progname, fn, strerror(errno));
return 1;
}
while ((len = getline(&line, &llen, f)) > 0) {
// … code to determine column widths
}
rewind(f);
}
// Code to read the file names from f follows
}
如果文件名不是-
(指示从标准输入读取),则代码读取文件两次,一次确定文件名的最大宽度,一次处理文件。对rewind
的调用缺少错误处理。使用-
作为文件名,代码不会尝试对齐列。
答案 1 :(得分:-2)
使用$(cmd)而不是使用&lt;(cmd)语法。这应该克服错误