Hướng dẫn giải quyết lỗi "Argument list too long" khi xóa hàng ngàn/hàng triệu tệp trong một thư mục – do giới hạn kích thước đối số dòng lệnh của kernel (ARG_MAX, thường ~2MB).
Ví dụ lỗi
root@server /var/spool/clientmqueue # rm spam-*
/bin/rm: Argument list too long
Giải pháp 1: find + xargs (Khuyến khích – chuẩn POSIX)
# find . -name 'spam-*' -type f -print0 | xargs -0 rm -f
find . -name 'spam-*' -type f: Tìm tệp (không phải thư mục) khớp pattern.-print0: Xuất tên tệp phân cách bằng null byte (\0) – an toàn cho tên có khoảng trắng, ký tự đặc biệt.xargs -0: Đọc input phân cách null byte.rm -f: Xóa, bỏ qua lỗi nếu không tồn tại.
Giải pháp 2: find -exec (Đơn giản, không cần xargs)
# find . -name 'spam-*' -type f -exec rm -f {} +
-exec ... +: Gom nhiều tệp vào một lệnhrm(tương tự xargs, nhưng built-in).- Thay
+bằng\;để chạyrmriêng cho từng tệp (chậm hơn).
Giải pháp 3: Bash globstar + vòng lặp (chỉ Bash 4+)
# shopt -s globstar nullglob
# for f in spam-*; do rm -f "$f"; done
- Shell tự mở rộng glob, không bị giới hạn ARG_MAX (vì không truyền qua execve).
- Chậm hơn find+xargs do overhead shell.
Giải pháp 4: rsync (Xóa thư mục lớn cực nhanh)
# mkdir /tmp/empty
# rsync -a --delete /tmp/empty/ /var/spool/clientmqueue/
# rmdir /tmp/empty
- Kỹ thuật "rsync delete into empty dir" – nhanh nhất cho hàng triệu tệp nhỏ.
- Giữ nguyên thư mục đích, chỉ xóa nội dung.
Giải pháp 5: Perl/Python one-liner
# perl -e 'for(){unlink}' # Perl glob không bị ARG_MAX
# python3 -c "import glob,os; [os.remove(f) for f in glob.glob('spam-*')]"
Xóa TOÀN BỘ tệp trong thư mục (cẩn thận!)
# find . -type f -delete # Chỉ xóa file, giữ thư mục con
# find . -mindepth 1 -delete # Xóa file VÀ thư mục con (rỗng sau khi xóa file)
# rsync -a --delete /tmp/empty/ ./ # Nhanh nhất
Tăng ARG_MAX (Không khuyến khích)
Có thể tăng giới hạn kernel:
# sysctl -w kernel.arg_max=10485760 # 10MB (tạm thời)
# echo 'kernel.arg_max=10485760' >> /etc/sysctl.d/99-argmax.conf # Vĩnh viễn
Nhưng cách này không giải quyết gốc rễ (thiết kế ứng dụng) và có rủi ro stack overflow.
Tóm tắt khuyến nghị
| Tình huống | Cách tốt nhất |
|---|---|
| Xóa file theo pattern (spam-*) | find . -name 'spam-*' -type f -exec rm -f {} + |
| Xóa toàn bộ nội dung thư mục lớn (>100k file) | rsync -a --delete /tmp/empty/ /path/to/dir/ |
| Xóa đệ quy cả thư mục con | find . -mindepth 1 -delete (GNU find) |
| Script portable (sh/dash) | find ... -print0 | xargs -0 rm |