Computer >> Hướng Dẫn Máy Tính >  >> Điện Thoại Thông Minh >> Linux

Cách khắc phục lỗi '/bin/rm: Argument list too long' khi xóa nhiều tệp trong Linux

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ệnh rm (tương tự xargs, nhưng built-in).
  • Thay + bằng \; để chạy rm riê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ốngCá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 confind . -mindepth 1 -delete (GNU find)
Script portable (sh/dash)find ... -print0 | xargs -0 rm