[英]Trouble with the process substitution in the file command
更容易显示为试图用文字描述。
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)
以上用作bash
diff /dev/fd/... /dev/fd/...
例如在grep
- 你可以使用:
grep -f <(command_for_produce_the_patterns) files..
再次, bash
内部使用它作为
grep -f /dev/fd/63 files....
所以,同样应该在file
工作
file -f <(command)
你做得对。 这是你的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
的调用缺少错误处理。 使用-
作为文件名,代码不会尝试对齐列。
不使用<(cmd)语法,而是使用$(cmd)。 这应该克服这个bug
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.