我必须得到一个包含大约 200 万个文件的目录列表,但是当我对它执行ls
命令时,什么都没有返回。我等了3个小时。我试过ls | tee directory.txt
了,但这似乎永远挂起。
我假设服务器正在进行大量的 inode 排序。有什么方法可以加快ls
命令以获取文件名的目录列表?我现在不在乎大小、日期、许可等。
ls -U
将执行 ls 而不进行排序。
另一个缓慢的来源是--color
. 在一些 linux 机器上,有一个方便的别名添加--color=auto'
到 ls 调用中,使其查找找到的每个文件的文件属性(慢),以着色显示。这可以通过ls -U --color=never
或避免\ls -U
。
我有一个目录,里面有 400 万个文件,我让 ls 立即吐出文件而无需先进行大量搅动的唯一方法是
ls -1U
尝试使用:
find . -type f -maxdepth 1
这只会列出目录中的文件,-type f
如果要列出文件和目录,请省略参数。
这个问题似乎很有趣,我正在查看已发布的多个答案。为了了解发布的答案的效率,我在 200 万个文件上执行了它们,发现结果如下。
$ time tar cvf /dev/null . &> /tmp/file-count
real 37m16.553s
user 0m11.525s
sys 0m41.291s
------------------------------------------------------
$ time echo ./* &> /tmp/file-count
real 0m50.808s
user 0m49.291s
sys 0m1.404s
------------------------------------------------------
$ time ls &> /tmp/file-count
real 0m42.167s
user 0m40.323s
sys 0m1.648s
------------------------------------------------------
$ time find . &> /tmp/file-count
real 0m2.738s
user 0m1.044s
sys 0m1.684s
------------------------------------------------------
$ time ls -U &> /tmp/file-count
real 0m2.494s
user 0m0.848s
sys 0m1.452s
------------------------------------------------------
$ time ls -f &> /tmp/file-count
real 0m2.313s
user 0m0.856s
sys 0m1.448s
------------------------------------------------------
总结结果
ls -f
command 的运行速度比ls -U
. 禁用颜色可能会导致这种改进。find
命令以 2.738 秒的平均速度运行第三。ls
了 42.16 秒。在我的系统中,这ls
是一个别名ls --color=auto
echo ./*
运行了 50.80 秒。tar
基于解决方案花费了大约 37 分钟。当系统处于空闲状态时,所有测试都是单独进行的。
这里要注意的一件重要事情是,文件列表不会在终端中打印,而是被重定向到文件,并且稍后使用wc
命令计算文件计数。如果输出打印在屏幕上,则命令运行速度太慢。
任何想法为什么会发生这种情况?
使用
ls -1 -f
大约快 10 倍,而且很容易做到(我测试了 100 万个文件,但我原来的问题有 6 800 000 000 个文件)
但就我而言,我需要检查某个特定目录是否包含超过 10 000 个文件。如果有超过 10 000 个文件,我不再对有多少文件感兴趣。我只是退出了该程序,以便它运行得更快,并且不会尝试一一阅读其余内容。如果少于 10 000,我将打印确切的数量。如果您为参数指定的值大于文件数量,我的程序的速度与 ls -1 -f 非常相似。
您可以通过键入以下内容在当前目录中使用我的程序 find_if_more.pl:
find_if_more.pl 999999999
如果您只是对有超过 n 个文件感兴趣,那么脚本将比 ls -1 -f 更快地完成大量文件。
#!/usr/bin/perl
use warnings;
my ($maxcount) = @ARGV;
my $dir = '.';
$filecount = 0;
if (not defined $maxcount) {
die "Need maxcount\n";
}
opendir(DIR, $dir) or die $!;
while (my $file = readdir(DIR)) {
$filecount = $filecount + 1;
last if $filecount> $maxcount
}
print $filecount;
closedir(DIR);
exit 0;
这将是最快的选项 AFAIK: ls -1 -f
。
-1
(无列)-f
(没有排序)您可以重定向输出并在后台运行 ls 进程。
ls > myls.txt &
这将允许您在运行时继续您的业务。它不会锁定你的外壳。
不确定运行 ls 和获取更少数据的选项有哪些。你可以随时跑过去man ls
检查。
这可能不是一个有用的答案,但如果你没有,find
你可以凑合tar
$ tar cvf /dev/null .
比我年长的人告诉我,“回到过去”,单用户和恢复环境比现在更受限制。这就是这个技巧的来源。
我假设您使用的是 GNU ls?尝试
\ls
它将取消通常的 ls (ls --color=auto) 的别名。
如果一个进程“没有回来”,我建议使用strace来分析一个进程是如何与操作系统交互的。
如果是 ls:
$strace ls
您会看到它在实际输出任何内容之前读取了所有目录条目( getdents(2) )。(排序……正如这里已经提到的)
怎么样find ./ -type f
(它将找到当前目录中的所有文件)?取下来-type f
找到一切。
要尝试的事情:
检查 ls 没有别名?
alias ls
也许尝试 find ?
find . \( -type d -name . -prune \) -o \( -type f -print \)
希望这可以帮助。
您使用的是什么分区类型?
在一个目录中有数百万个小文件,使用 JFS 或 ReiserFS 可能是一个好主意,它们对许多小文件有更好的性能。
一些后续行动:您没有提及您正在运行的操作系统,这将有助于指示您正在使用的 ls 版本。这可能不像 ls 问题那样是“bash”问题。我的猜测是您使用的是 GNU ls,它具有一些在某些情况下有用的功能,但在大目录中会杀死您。
GNU ls 试图对列进行更漂亮的排列。GNU ls 尝试对所有文件名进行智能排列。在一个巨大的目录中,这将需要一些时间和内存。
要“解决”这个问题,您可以尝试:
ls -1
# 根本没有列
在某个地方找到 BSD ls,http: //www.freebsd.org/cgi/cvsweb.cgi/src/bin/ls/并在您的大目录中使用它。
使用其他工具,例如 find
有几种方法可以获取文件列表:
使用此命令获取不排序的列表:
ls -U
或使用以下命令将文件列表发送到文件:
ls /Folder/path > ~/Desktop/List.txt
我有一个文件名中带有时间戳的目录。我想检查最新文件的日期,发现find . -type f -maxdepth 1 | sort | tail -n 1
它的速度大约是ls -alh
.
这里有很多其他好的解决方案,但为了完整性:
echo *
您还可以使用xargs。只需通过xargs管道输出ls的输出。
ls | xargs
如果这不起作用并且上面的查找示例不起作用,请尝试将它们通过管道传输到xargs,因为它可以帮助内存使用可能导致您的问题。