据我所知,命令如
find <dir> -type f -exec rm {} \;
不是删除大量文件(总文件,包括子文件夹)的最佳变体。如果您有少量文件,它会很好用,但如果您的子文件夹中有 10 多个 mlns 文件,它可能会挂起服务器。
有谁知道任何特定的linux命令来解决这个问题?
这可能看起来很奇怪,但是:
$ rm -rf <dir>
这是一个示例 bash 脚本:
#!/bin/bash
local LOCKFILE=/tmp/rmHugeNumberOfFiles.lock
# this process gets ultra-low priority
ionice -c2 -n7 -p $$ > /dev/null
if [ $? ]; then
echo "Could not set disk IO priority. Exiting..."
exit
fi
renice +19 -p $$ > /dev/null
if [ $? ]; then
echo "Could not renice process. Exiting..."
exit
fi
# check if there's an instance running already. If so--exit
if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then
echo "An instance of this script is already running."
exit
fi
# make sure the lockfile is removed when we exit. Then: claim the lock
trap "command rm -f -- $LOCKFILE; exit" INT TERM EXIT
echo $$ > $LOCKFILE
# also create a tempfile, and make sure that's removed too upon exit
tmp=$(tempfile) || exit
trap "command rm -f -- '$tmp'" INT TERM EXIT
# ----------------------------------------
# option 1
# ----------------------------------------
# find your specific files
find "$1" -type f [INSERT SPECIFIC SEARCH PATTERN HERE] > "$tmp"
cat $tmp | rm
# ----------------------------------------
# option 2
# ----------------------------------------
command rm -r "$1"
# remove the lockfile, tempfile
command rm -f -- "$tmp" $LOCKFILE
该脚本首先将自己的进程优先级和磁盘IO 优先级设置为非常低的值,以确保其他正在运行的进程尽可能不受影响。
然后它确保它是唯一运行的此类进程。
脚本的核心完全取决于您的喜好。如果您rm -r
确定可以随意删除整个目录(选项 2),则可以使用,或者您可以find
用于更具体的文件删除(选项 1,可能使用命令行选项“$2”和 onw。为方便起见)。
在上面的实现中,选项 1 ( find
) 首先将所有内容输出到一个临时文件,因此该rm
函数仅被调用一次,而不是在find
. 当文件数量确实很大时,这可以节省大量时间。不利的一面是,临时文件的大小可能会成为一个问题,但这仅在您要删除数十亿个文件时才有可能,另外,由于 diskIO 的优先级如此之低,因此使用一个临时文件后跟一个单个文件rm
可能总共是比使用find (...) -exec rm {} \;
选项慢。与往常一样,您应该进行一些试验,看看最适合您的需求。
编辑:根据 user946850 的建议,您也可以跳过整个临时文件并使用
find (...) -print0 | xargs -0 rm
. 这具有更大的内存占用,因为所有匹配文件的所有完整路径都将插入 RAM 中,直到find
命令完全完成。好的一面是:由于写入临时文件,没有额外的文件 IO。选择哪一个取决于您的用例。
(-r
递归)开关也删除目录下的所有内容 - 包括子目录。(您的命令不会删除目录,只会删除文件。)
您还可以加快find
方法:
find -type f -print0 | xargs -0 rm
如果您有相当现代的 find 版本(4.2.3 或更高版本),您可以使用 -delete 标志。
find <dir> -type f -delete
\+
如果您有 4.2.12 或更高版本,则可以通过-exec 修饰符利用 xargs 样式的命令行堆栈。这样您就不会/bin/rm
为每个文件运行单独的副本。
find <dir> -type f -exec rm {} \+
前面的命令很好。
rm -rf directory/
也可以更快地处理一个文件夹中的数十亿个文件。我试过了。
我尝试了这些命令中的每一个,但我遇到的问题是删除进程正在锁定磁盘,并且由于没有其他进程可以访问它,因此有大量进程试图访问磁盘,使问题变得更糟。运行“iotop”并查看您的进程正在使用多少磁盘 IO。
这是解决我的问题的python脚本。它一次删除 500 个文件,然后需要 2 秒的休息时间让其他进程处理它们的业务,然后继续。
import os, os.path
import time
for root, dirs, files in os.walk('/dir/to/delete/files'):
i = 0
file_num = 0
for f in files:
fullpath = os.path.join(root, f)
i = i + 1
file_num = file_num + 1
os.remove(fullpath)
if i%500 == 1:
time.sleep(2)
print "Deleted %i files" % file_num
希望这可以帮助一些人。
如果您需要处理非常大的文件树(在我的情况下是许多 perforce 分支)上的空间限制问题,有时在运行查找和删除过程时会被挂起 -
这是我每天安排的一个脚本,用于查找具有特定文件(“ChangesLog.txt”)的所有目录,然后对找到的所有超过2 天的目录进行排序,并删除第一个匹配的目录(每个安排都可能有一个新的匹配):
bash -c "echo @echo Creating Cleanup_Branch.cmd on %COMPUTERNAME% - %~dp0 > Cleanup_Branch.cmd"
bash -c "echo -n 'bash -c \"find ' >> Cleanup_Branch.cmd"
rm -f dirToDelete.txt
rem cd. > dirToDelete.txt
bash -c "find .. -maxdepth 9 -regex ".+ChangesLog.txt" -exec echo {} >> dirToDelete.txt \; & pid=$!; sleep 100; kill $pid "
sed -e 's/\(.*\)\/.*/\1/' -e 's/^./"&/;s/.$/&" /' dirToDelete.txt | tr '\n' ' ' >> Cleanup_Branch.cmd
bash -c "echo -n '-maxdepth 0 -type d -mtime +2 | xargs -r ls -trd | head -n1 | xargs -t rm -Rf' >> Cleanup_Branch.cmd"
bash -c 'echo -n \" >> Cleanup_Branch.cmd'
call Cleanup_Branch.cmd
注意要求:
如果您想尽快删除大量文件,请尝试以下操作:
find . -type f -print0 | xargs -P 0 -0 rm -f
请注意,该-P
选项将xargs
尽可能多地使用进程。
mv large_folder /tmp/.
sudo reboot
调用 mv 很快——它只是修改标签。系统重新启动将以最快的方式清除 /tmp 文件夹(再次挂载它?)。
您可以创建一个空目录并将其 RSYNC 到您需要清空的目录。您将避免超时和内存不足的问题