我有一个目录,其中非常快地生成了许多缓存文件。由于这些文件非常小,因此它会很快消耗我的所有 inode。
目前我正在运行以下命令来查找所有早于 12 小时的文件并删除它们。
$ find ./cache -mtime +0.5 -exec rm {} \;
但是此命令删除的速度比生成文件的速度慢。有人可以告诉我一些快速删除大量文件的替代方法。
欢迎各位兄弟 发布技术文章
这里的技术是共享的
1) rm:删除数百万个文件是不可能的!
2) find -exec:一个选项,但速度较慢!
3) find -delete:快速简便地删除大量文件。 # find ./tmp3 -type f -delete OK OK OK
4) rsync --delete:毫无疑问是最快的! (为什么我在红帽5上试了 rsync 特别的慢)
6) ls -1 -f | grep .txt | xargs -I {} rm -f {} #太慢,不予考虑,,因为大约好几个小时吧
7) rm -Rf directory # rm -Rf ./tmp3 这个与 find -delete 速度关不多了吧 OK OK OK
8) perl 我使用perl方法 也是非常的慢
当在几万以下时,好像 rm 的速度还算可以
[root@node1 ~]# time rm -Rf tmp3/*
-bash: /bin/rm: 参数列表过长 #连执行都无法执行了,肯定最慢
real 0m6.292s
user 0m4.210s
sys 0m1.433s
[root@node1 ~]#
[root@node1 ~]# time rm -Rf tmp4
real 0m35.835s
user 0m0.181s
sys 0m22.232s
[root@node1 ~]#
[root@node1 ~]# time find ./tmp3 -type f -delete
real 0m31.126s
user 0m0.143s
sys 0m14.970s
[root@node1 ~]#
[root@node1 ~]# time ls -1 -f tmp2 | xargs -I {} rm -rf tmp2/{}
rm: 无法删除“.”或“..”
rm: 无法删除“.”或“..”
real 6m8.948s #6分多钟太慢了
user 0m19.780s
sys 4m5.675s
[root@node1 ~]#
[root@node1 ~]# time find ./tmp1 -type f -exec rm -rf {} \;
real 10m57.554s #10分多钟太慢了
user 0m35.156s
sys 6m45.784s
[root@node1 ~]#
[root@mail home]# time rsync -a --delete /tmp/empty tmp4/ # /tmp/empty 不能有斜线 tmp4/ 后面必须有斜线
real 0m0.715s #不知什么原因 ,好像这个命令有问题
user 0m0.040s
sys 0m0.638s
[root@mail home]#
我最近遇到了这个问题,我错误地有超过 2700 万个小文件,每个文件都在一个目录中不到 100KB。当我想将它们全部删除时,rm命令无法正常工作,需要很长时间才能完成,那有什么问题呢?问题是为列表中的每个文件调用 rm 命令。例如,如果文件夹中有50个大于7M的文件,则调用50条rm命令删除每个文件。这将需要更长的时间。
那么有没有其他方法可以解决这个问题?
例子:
find /test -type f -exec rm {}
上面显示的命令将删除 /test 目录中的所有文件。首先 find 命令会查找目录内的所有文件,然后对于每个结果,它会执行并 rm
本质上这个命令与 rm 命令没有什么不同,但是,实际上,这会比原始 rm 命令快一点。一百万个文件大约需要 14 分钟,具体取决于您的个人文件大小。
例子:
find ./ -type f -delete
这个命令实际上比上面的命令快得多。一百万个文件大约需要 5 分钟,具体取决于您的个人文件大小。
例子:
perl -e 'for(<*>){((stat)[9]<(unlink))}'
这实际上是最胖的选择。处理一百万个文件大约需要 1 分钟,具体取决于您的个人文件大小。
但是,是的,如果您对使用 Perl 删除文件感兴趣,则需要对 Perl 正则表达式有一定的了解。
还有一种较少使用且鲜为人知的方法可用于删除文件夹内的大量文件。这种方法正是我们著名的工具 RSYNC,用于在 Linux 中的两个本地和远程位置之间传输和同步文件
这可以通过简单地将具有大量文件的目标目录与空目录同步来实现。在我们的例子中,test 目录有 50 万个文件,让我们创建一个名为 blanktest 的目录,为了简单同步,它将保持为空。现在,我们将在 rsync 中使用 -delete 选项,这将删除目标目录中的所有文件,这些文件在源文件中不存在
例子:
空目录:/home/blanktest
要清空的目录:/test
rsync -a --delete blanktest/ test/ #两个文件夹后面的斜杠都不能省略
此命令大约需要 2 分钟才能删除所有文件。凉爽的!
Linux等操作系统在文件系统上有一定的限制,一个目录下放太多文件不是一个好主意,如果你想存储大量文件,最好将这些文件存储在子目录下一个子目录中的理想文件数量少于 10000。
来自 https://yonglhuang.com/rm-file/
最后更新: 13/01/2016
它发生在最好的情况下:一些脚本飞到天际线,导致即时系统管理员头疼,因为某些文件夹 - 通常是会话 - 塞满了数百万个文件。Linux 对此不太满意,删除文件夹不是一个选项,忠实的“rm -rf ”命令决定结束它。更糟糕的是:您只想删除几天前的文件......有哪些选择?
来自 https://www.kinamo.be/en/support/faq/efficiently-remove-a-zillion-files-on-linux-servers
尝试使用xargs
:
find ./cache -mtime +0.5 -print0 | xargs -0 rm -f
@pradeepchhetri 的更新说明
如果使用find
with -exec
,find
找到的每个文件都会调用rm
一次。因此,如果您发现大量文件,即 10000 个文件,则调用rm
10000 次。
xargs
将把输出find
作为命令参数rm
,因此,xargs 将提供尽可能多的参数rm
,即一次可以处理,即rm -f file1 file2 ...
因此它减少了 fork 调用,使程序运行得更快。
find
启动一个新rm
进程。使用 Gnouc 的方法,xargs
只rm
为一堆文件启动一个实例。启动更少的程序使其更快。 —— 库尔特姆 2013 年 10 月 21 日 11:31 find … -exec rm {} \;
rm
为每个文件执行命令。尽管启动一个新进程非常快,但它仍然比仅仅删除文件的行为慢得多。
find … -exec rm {} +
会rm
分批调用,这样会快很多:你支付rm
每批运行一次的成本,每批执行多次删除。
甚至更快的是根本不调用rm
。在find
对Linux命令有一个动作-delete
来删除一个匹配的文件。
find ./cache -type f -mtime +0.5 -delete
但是,如果您以find … -exec rm {} \;
跟不上的速度生成文件,则您的设置可能有问题。如果cache
包含数百万个文件,您应该将其拆分为子目录以加快访问速度。
find -delete
拯救了这一天;在 rm 删除大约 2 万个文件的同时删除了大约 650 万个文件。 —— 学霸 2018-02-27 18:50./cache
包含子目录,这些内容也将被删除,但正如所写, find 将在删除内容之前尝试删除目录。这里有解决方案: 1.-depth
如果需要删除子目录,则添加。和 2. 添加-type f
以避免尝试删除子目录。另一种限制到 CURRENT 目录的方法是使用-prune
- 容易被逗乐的史蒂文 20 年 7 月 25 日 17:49-delete
自动打开-prune
。但是跳过目录是个好主意: find 不会删除非空目录,但会发出错误信号。 —— 吉尔斯'所以-停止邪恶' 20 年 7 月 25 日 19:38虽然 find 是最好的(最简单的,惯用的)方法,
find $dir -exec rm {} +
您可以将目录移到一边,创建一个新目录(为您的程序),然后删除...
mv $idr old$dir && mkdir $dir && rm -rf old$dir
但也许您的问题是创建了太多文件。为什么不更改您的程序以附加到现有文件,而不是创建一个新文件?然后你可以把这个(日志文件)移到一边,然后你的程序可以创建/附加到一个新文件,例如,
fd = open("logfile","a+");
如果创建率超过删除率,您最好将缓存完全清空,并在没有任何 mtime 评估的情况下删除旧文件
mv cache foobar
mkdir cache
# may require app restart
rm -rf foobar
如果您只是想尽快删除许多文件可能ls -f1 /path/to/folder/with/many/files/ | xargs rm
会工作得很好,但最好不要在生产系统上运行它,因为您的系统可能会出现 IO 问题并且应用程序可能会在删除操作期间卡住。
此脚本适用于许多文件,不会影响系统的 ioload。
#!/bin/bash
# Path to folder with many files
FOLDER="/path/to/folder/with/many/files"
# Temporary file to store file names
FILE_FILENAMES="/tmp/filenames"
if [ -z "$FOLDER" ]; then
echo "Prevented you from deleting everything! Correct your FOLDER variable!"
exit 1
fi
while true; do
FILES=$(ls -f1 $FOLDER | wc -l)
if [ "$FILES" -gt 10000 ]; then
printf "[%s] %s files found. going on with removing\n" "$(date)" "$FILES"
# Create new list of files
ls -f1 $FOLDER | head -n 5002 | tail -n 5000 > "$FILE_FILENAMES"
if [ -s $FILE_FILENAMES ]; then
while read FILE; do
rm "$FOLDER/$FILE"
sleep 0.005
done < "$FILE_FILENAMES"
fi
else
printf "[%s] script has finished, almost all files have been deleted" "$(date)"
break
fi
sleep 5
done
rm -rf directory/ 也可以更快地处理一个文件夹中的十亿个文件。我试过了。
另一个特定于 Linux 的解决方案是使用inotify(7)设施;您将检测何时添加文件,然后您将立即运行某些程序以删除旧文件。
OTOH,我猜你可能有一些XY 问题。为什么你有这么多新文件?也许使用 sqlite,或 GDBM 索引文件,或者一些真实的数据库(例如 PostGresQL、MariaDB、MongoDB)可能会更好......也许你需要一些像git这样的版本控制系统?
find . -name -mtime +0.5 -print -delete
是快速删除大量文件的另一种选择。
./cache
这个答案假设 ./cache 是当前目录 - 它不会是每个 OP。其次,添加-print
将喷出(数万)数千行输出。还有一个微妙的问题:如果当前目录中有子目录,它会尝试(并且失败)删除它们——除非它们已经是空的……但这也可能是不受欢迎的!为什么:因为 find 从每个子目录开始执行深度优先搜索。 —— 容易被逗乐的史蒂文 20 年 7 月 25 日 17:41来自 https://unix.stackexchange.com/questions/96935/faster-way-to-delete-large-number-of-files/211650
我们有一个文件夹变得笨重的问题,其中包含数十万个小文件。
执行rm -rf
返回错误的文件太多了,而我们需要做的是:
find /path/to/folder -name "filenamestart*" -type f -exec rm -f {} \;
这有效,但速度非常慢,并且经常因内存不足而失败。
有一个更好的方法吗?理想情况下,我想删除整个目录而不关心其中的内容。
fsck
在其上运行以回收未使用的磁盘块,但这种方法似乎有风险并且可能不会更快。此外,文件系统检查可能涉及递归遍历文件系统树。 —— jw013 2012 年 4 月 26 日 13:27 ccache
如此庞大的文件树,并且rm
花费了如此长的时间(并使整个系统变得缓慢),从文件系统中复制所有其他文件,格式化并复制回它们的速度要快得多。从那时起,我为如此庞大的小文件树提供了自己的专用文件系统,因此您可以mkfs
直接代替rm
. —— 霜舒茨 2013 年 6 月 15 日 11:43使用 rsync 非常快速和简单。
mkdir empty_dir
rsync -a --delete empty_dir/ yourdirectory/
@sarath 的回答提到了另一个快速选择:Perl!它的基准测试比rsync -a --delete
.
cd yourdirectory
perl -e 'for(<*>){((stat)[9]<(unlink))}'
或者,没有stat
(是否需要它是有争议的;有人说使用它可能更快,而其他人说没有它更快):
cd yourdirectory
perl -e 'for(<*>){unlink}'
资料来源:
rsync
可以比 plain 更快rm
,因为它保证删除的顺序正确,因此需要更少的 btress 重新计算。请参阅此答案serverfault.com/a/328305/105902 – 马克555 2015-06-29 12:45-P
为 rsync添加选项以获得更多显示,另外,注意语法,尾部斜杠是强制性的。最后,您可以使用-n
first to launch a dry run选项第一次启动 rsync 命令。 —— 德拉西尔 2015 年 10 月 23 日 15:39在有人Twitter的使用建议-delete
,而不是-exec rm -f{} \;
这提高了命令的效率,但它仍然使用递归来遍历所有内容。
一个巧妙的技巧:
rsync -a --delete empty/ your_folder/
这是超级 CPU 密集型,但真的非常快。见https://web.archive.org/web/20130929001850/http://linuxnote.net/jianingy/en/linux/a-fast-way-to-remove-huge-number-of-files.html
rsync -a --delete
vs 43秒lsdent
。10X是为比 time ls -1 | wc -l
VS time ./dentls bigfolder >out.txt
(即由于部分公平的比较 > file
VS wc -l
)。 —— 哈斯塔 2016 年 1 月 21 日 9:30怎么样: find /path/to/folder -name "filenamestart*" -type f -print0 | xargs -0rn 20 rm -f
您可以通过更改 parameter 的参数来限制一次删除的文件数-n
。还包括带空格的文件名。
man xargs
:的注释(...) max-chars characters per command line (...). The largest allowed value is system-dependent, and is calculated as the argument length limit for exec
。因此,-n
选项适用于 xargs 无法确定 CLI 缓冲区大小或执行的命令有一些限制的情况。 —— digital_infinity 2012 年 4 月 26 日,13:50 扩展其中一条评论,我认为您没有在做您认为正在做的事情。
首先,我创建了大量文件,以模拟您的情况:
$ mkdir foo
$ cd foo/
$ for X in $(seq 1 1000);do touch {1..1000}_$X; done
然后我尝试了我期望失败的方法,以及您在问题中所做的事情:
$ rm -r foo/*
bash: /bin/rm: Argument list too long
但这确实有效:
$ rm -r foo/
$ ls foo
ls: cannot access foo: No such file or directory
rm -Rf bigdirectory
多次运行。我有一个包含数以百万计的子目录和文件的目录。我什至无法在该目录中运行ls
orfind
或rsync
,因为它的内存不足。该命令rm -Rf
多次退出(内存不足),仅删除了数十亿个文件中的一部分。但经过多次重试后,它终于完成了这项工作。如果内存不足是问题,这似乎是唯一的解决方案。 —— 埃里克 2014 年 4 月 9 日 13:01 我有机会测试-delete
相比-exec rm \{\} \;
,对我来说-delete
就是这个问题的答案。
使用-delete
删除文件夹中 400,000 个文件的文件至少比rm
.
“如何在 linux 中删除大量文件”一文表明它大约快了三倍,但在我的测试中,差异要大得多。
-exec rm {} \+
派上用场的\+
地方(特别是in 的地方\;
),因为它像内置的 xargs 一样工作,没有最小的管道和叉开销。不过,仍然比其他选项慢。 —— 丹尼绍尔 19 年 12 月 2 日 23:12execplus
于 1988 年由 AT&T 的 David Korn 发明,而 GNU find 是最后一个添加支持的 find 实现 - 25 多年后。顺便说一句:标准execplus
和非标准之间的速度差异-delete
很小。 —— 狡猾的 20 年 2 月 22 日 10:09rm -rf directory
代替rm -rf *
。我们最初rm -rf *
是在目录中清除内容,并认为这是尽可能快的。但是后来我们的一位高级工程师建议我们避免使用星号 ( *
),而是传入父目录,例如rm -rf directory
.
在关于这不会产生什么影响的激烈辩论之后,我们决定对其进行基准测试,以及使用find
. 结果如下:
time rm -rf * 2m17.32s
time rm -rf directory 0m15.60s
time find directory -delete 0m16.97s
rm -rf directory
大约比rm -rf *
!快 9 倍!
不用说,我们给那个工程师买了啤酒!
所以现在我们使用rm -rf directory; mkdir directory
删除目录并重新创建它。
关于-delete
上面的选项:我正在使用它删除我创建的临时文件夹中的大量(1M+ est)文件,但无意中忘记了每晚清理。我不小心填满了我的磁盘/分区,除了find .
命令之外没有其他任何东西可以删除它们。它很慢,起初我使用的是:
find . -ls -exec rm {} \;
但这需要花费大量时间。它在大约 15 分钟后开始删除一些文件,但我的猜测是它在最终启动后每秒删除不到 10 个左右。所以,我尝试了:
find . -delete
相反,我现在让它运行。它似乎运行得更快,尽管它对 CPU 的负担非常大,而另一个命令则没有。它已经运行了大约一个小时,我想我的驱动器上的空间正在恢复,并且分区逐渐“缩小”,但仍然需要很长时间。我严重怀疑它的运行速度比另一个快 1,000 倍。和所有事情一样,我只是想指出空间与时间的权衡。如果您有足够的 CPU 带宽(我们有),则运行后者。它让我的 CPU 正在运行(uptime
报告):
10:59:17 up 539 days, 21:21, 3 users, load average: 22.98, 24.10, 22.87
我已经看到平均负载超过 30.00,这对于繁忙的系统来说并不好,但是对于我们通常负载较轻的系统来说,几个小时就可以了。我已经检查了系统上的大多数其他内容,它们仍然有响应,所以我们现在还可以。
exec
你几乎肯定不想使用-ls
并且 do find . -type f -exec rm '{}' +
+ 更快,因为它会给 rm 提供尽可能多的参数,因为它可以一次处理。 —— 异种草酸 2014 年 1 月 3 日 17:48find … -delete
通过nice
或运行它ionice
,这可能会有所帮助。因此可能会将某些挂载选项更改为不太安全的设置。(当然,根据文件系统上的其他内容,删除所有内容的最快方法通常是mkfs
。) – 德罗贝特 2014 年 1 月 4 日 7:24 1
,单核机器的 loadavg64
与 64 核系统的loadavg 相同- 意味着每个 CPU 100% 的时间都处于忙碌状态。 —— 马克555 2015-06-29 12:49有几种方法可用于在 linux 中删除大量文件。您可以将 find 与 delete 选项一起使用,这比 exec 选项更快。然后你可以使用 perl unlink,然后甚至是 rsync。 linux下如何删除大量文件
删除非常大的目录需要一种不同的方法,正如我从这个站点学到的那样 - 你需要利用 ionice。它确保(使用 -c3)只有在系统有 IO 时间时才会执行删除。您的系统负载不会上升到很高,并且一切都保持响应(尽管我的 CPU 查找时间相当高,约为 50%)。
find <dir> -type f -exec ionice -c3 rm {} \;
如果您有数百万个文件并且上述每个解决方案都让您的系统承受压力,您可以尝试以下灵感:
文件nice_delete
:
#!/bin/bash
MAX_LOAD=3
FILES=("$@")
BATCH=100
while [ ${#FILES[@]} -gt 0 ]; do
DEL=("${FILES[@]:0:$BATCH}")
ionice -c3 rm "${DEL[@]}"
echo -n "#"
FILES=("${FILES[@]:$BATCH}")
while [[ $(cat /proc/loadavg | awk '{print int($1)}') -gt $MAX_LOAD ]]; do
echo -n "."
sleep 1
done
done
现在删除文件:
find /path/to/folder -type f -exec ./nice_delete {} \+
Find 将创建成批(请参阅 参考资料getconf ARG_MAX
)的数万个文件并将其传递给nice_delete
. 这将创建更小的批次,以便在检测到过载时允许休眠。
ls -1 | xargs rm -rf
应该在主文件夹内工作
find . -print0 | xargs -0 rm
,它将使用 NULL 字符作为文件名分隔符。 —— 马克555 2015-06-29 12:51对于上面 Izkata 的提示:
但这确实有效:
$ rm -r foo/ $ ls foo ls: cannot access foo: No such file or directory
这几乎奏效了——或者本来可以奏效的——但是我在许可方面遇到了一些问题;文件在服务器上,但我仍然不明白这个权限问题的来源。无论如何,终端要求对每个文件进行确认。文件数量约为 20 000,所以这不是一个选项。在“-r”之后我添加了选项“-f”,所以整个命令是“ rm -r -f foldername / ”。然后它似乎工作正常。我是终端的新手,但我想这没问题,对吧?谢谢!
根据您需要摆脱这些文件的程度,我建议使用shred
.
$ shred -zuv folder
如果您想清除目录,但无法删除并重新创建它,我建议您移动它并立即重新创建它。
mv folder folder_del
mkdir folder
rm -rf folder_del
信不信由你,这更快,因为只需要更改一个 inode。请记住:您无法在多核计算机上真正并行执行此任务。这归结为磁盘访问,这受 RAID 或您的限制。
如果您只是想尽快删除许多文件可能ls -f1 /path/to/folder/with/many/files/ | xargs rm
会工作得很好,但最好不要在生产系统上运行它,因为您的系统可能会出现 IO 问题并且应用程序可能会在删除操作期间卡住。
此脚本适用于许多文件,不会影响系统的 ioload。
#!/bin/bash
# Path to folder with many files
FOLDER="/path/to/folder/with/many/files"
# Temporary file to store file names
FILE_FILENAMES="/tmp/filenames"
if [ -z "$FOLDER" ]; then
echo "Prevented you from deleting everything! Correct your FOLDER variable!"
exit 1
fi
while true; do
FILES=$(ls -f1 $FOLDER | wc -l)
if [ "$FILES" -gt 10000 ]; then
printf "[%s] %s files found. going on with removing\n" "$(date)" "$FILES"
# Create new list of files
ls -f1 $FOLDER | head -n 5002 | tail -n 5000 > "$FILE_FILENAMES"
if [ -s $FILE_FILENAMES ]; then
while read FILE; do
rm "$FOLDER/$FILE"
sleep 0.005
done < "$FILE_FILENAMES"
fi
else
printf "[%s] script has finished, almost all files have been deleted" "$(date)"
break
fi
sleep 5
done
使用ls -f | xargs -n 5000 rm
, 同时-n
根据您的系统调整批量大小(感谢@digital_infinity 的-n
提示)。
此外,您可以使用内联 grep 过滤列表,例如ls -f | grep '^156' | xargs -n 5000 rm
.
根据我的经验,这比使用 find 的技术快得多,并且不需要更复杂的 shell 脚本。
Python 脚本不应该被认为是不干净的:
#!/usr/bin/python3
import shutil
path_for_deletion = input( 'path of dir for deletion> ' )
print( 'about to remove ' + path_for_deletion + ' ...' )
shutil.rmtree( path_for_deletion, ignore_errors=True )
print( '... done' )
我问过在这里对各种方法做了一些有用的基准测试的人是否可以尝试对此进行基准测试。从我的实验来看,它看起来不错。
可以处理 NB 错误以至少将它们打印出来......但运行trash myDirectoryForDeletion
或rm -rfv myDirectoryForDeletion
之后运行可能更简单。
mtime
超过 12 小时的文件,对吗?如果文件生成得非常快,那么您可能需要删除比这更多的文件。 —— 约瑟夫·R。 2013 年 10 月 21 日 9:20\;
a+
或更好的用法,-delete
因为您似乎在使用 GNU find。 —— 斯蒂芬·查泽拉斯 2013 年 10 月 21 日 12:48