如何将文件列表过滤为存在的文件?
例如
echo 'a.txt
does/not.exist
b.txt' | <???>
会打印
a.txt
b.txt
您可以ls -d
文件并查看哪些文件获得一些输出。由于字符串中有它们,因此只需通过管道传输列表并使用xargs
即可ls
它们。
要隐藏错误,请将这些错误重定向到 /dev/null
。总之,xargs ls -d 2>/dev/null
做到了:
$ echo 'a.txt
b.txt
other' | xargs ls -d 2>/dev/null
a.txt
b.txt
如您所见,xargs ls -d
执行ls -d
给出的所有参数。 2>/dev/null
摆脱了标准消息。
如果您有 GNU xargs
,请使用 -d 'n'
来确保正确处理带有嵌入空格的文件名(包括目录),方法是将输入拆分为整行而不是行内空格。
echo 'a.txt
does/not.exist
b.txt' | xargs -d 'n' ls -1df 2>/dev/null
注意:
ls
命令为每个不存在的输入路径发出错误,2>/dev/null
忽略该错误,同时按原样回显现有路径。选项
-1
将每个路径打印在自己的行上,-d
防止递归到目录中,-f
防止对输入路径进行排序(如果确实要排序,请省略f
)。
在macOS/BSD上,xargs
不支持-d
,这需要使用tr
和xargs
的-0
选项通过NUL分隔的输入进行解决方法:
echo 'a.txt
does/not.exist
b.txt' | tr 'n' ' ' | xargs -0 ls -1df 2>/dev/null
作为单行,纯粹的速度猛击(从 mklement0 的答案改进,如果我有代表,我会发表评论):
{ ls; echo does/not.exist; } | while IFS= read -r f; do [[ -f "$f" ]] && echo "$f"; done
我想出的第一件事,在 while read 循环中使用 stats
的退出代码:
<input> | while IFS= read -r f; do stat "$f" &>/dev/null && echo "$f"; done
请注意,此解决方案很慢,因为它在 shell 代码中循环,并调用外部实用程序(创建子进程,stat
)在每次迭代中。
我会使用 bash 的 if 来检查文件。它最终有点不那么紧凑,但我认为它更清晰,并且更容易对结果中的每个找到的文件做一些事情。
它与带空格的文件名兼容。
echo 'a.txt
does/not.exist
b.txt' | while read filename
do
if [[ -f "$filename" ]]
then
echo $filename # Or do something else with the files here
fi
done
<</div>
div class="one_answers"> 可以将多个文件传递给stat
,如果文件不存在,则只会向STDERR打印一条消息。所以你可以这样做:
<input> | xargs stat --printf '%nn' 2> /dev/null
或者,如果您使用的是以 null 结尾的路径(我推荐并且无法使用 ls
):
<input> | xargs -0 stat --printf '%n ' 2> /dev/null