Danh sách đối số lỗi quá dài cho các lệnh rm, cp, mv


629

Tôi có hàng trăm tệp PDF trong một thư mục trong UNIX. Tên của các tệp PDF thực sự dài (khoảng 60 ký tự).

Khi tôi cố gắng xóa tất cả các tệp PDF cùng nhau bằng lệnh sau:

rm -f *.pdf

Tôi nhận được lỗi sau đây:

/bin/rm: cannot execute [Argument list too long]

Giải pháp cho lỗi này là gì? Có lỗi này xảy ra cho mvcpcác lệnh là tốt? Nếu có, làm thế nào để giải quyết cho các lệnh này?


21
Bạn có thể thấy liên kết này hữu ích
other.anon.coward


1
Ngoài ra, điều này có thể có liên quan http://mywiki.wooledge.org/BashFAQ/095
Lorenzo Belli

4
@jww: Và tôi đã tiếp tục suy nghĩ trong nhiều năm qua rằng bash rơi vào "công cụ phần mềm thường được lập trình viên sử dụng" - một danh mục mà câu hỏi của bạn có thể được hỏi ở đây!
Vicky

@Nik - Thêm "... trong tập lệnh" không hấp dẫn. Khi vấn đề được giảm xuống thành một ví dụ Tối thiểu, Hoàn thành và Có thể kiểm chứng , đó chỉ là một câu hỏi về cách chạy lệnh. Tôi xin lỗi nếu tôi thiếu một cái gì đó rõ ràng.
jww

Câu trả lời:


876

Lý do điều này xảy ra là vì bash thực sự mở rộng dấu hoa thị cho mọi tệp phù hợp, tạo ra một dòng lệnh rất dài.

Thử cái này:

find . -name "*.pdf" -print0 | xargs -0 rm

Cảnh báo: đây là một tìm kiếm đệ quy và cũng sẽ tìm thấy (và xóa) các tệp trong thư mục con. Tack trên -fcho lệnh rm chỉ khi bạn chắc chắn không muốn xác nhận.

Bạn có thể làm như sau để làm cho lệnh không đệ quy:

find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm

Một tùy chọn khác là sử dụng -deletecờ của find :

find . -name "*.pdf" -delete

7
Không, xargsđặc biệt chia nhỏ danh sách và đưa ra một số lệnh nếu cần thiết.
tripleee

7
@Dennis: -maxdepth 1cần phải là đối số đầu tiên sau đường dẫn.
Barton Chittenden

54
Find có một -deletecờ để xóa các tệp mà nó tìm thấy và ngay cả khi nó vẫn không được coi là thực hành tốt hơn để sử dụng -execđể thực thi rm, thay vì gọi xargs (hiện là 3 quy trình và một đường ống thay vì một quy trình đơn lẻ -deletehoặc 2 quá trình với -exec).
scragar

3
@ ÉdouardLopez ... Nhưng đây là cách đọc đầu vào được phân tách bằng NULL. Và toàn bộ dangerous (broken, exploitable, etc.), là khá vô lý. Chắc chắn bạn nên cẩn thận khi sử dụng xargs, nhưng nó không hoàn toàn eval/evil.
Phục hồi Monica Xin vui lòng

4
@scragar Với việc -execgọi rm, số lượng quy trình sẽ là 1 + số tệp, mặc dù số lượng quy trình đồng thời từ đây có thể là 2 (có thể tìm thấy sẽ thực thi đồng thời các quy trình rm). Số lượng quy trình sử dụng xargssẽ giảm đáng kể xuống còn 2 + n, trong đó n là một số quy trình ít hơn số lượng tệp (giả sử số lượng tệp / 10, mặc dù có thể nhiều hơn tùy thuộc vào độ dài của đường dẫn). Giả sử tìm thấy thực hiện xóa trực tiếp, sử dụng -deletenên là quá trình duy nhất sẽ được gọi.
thần kinh

396

tl; dr

Đó là một giới hạn hạt nhân về kích thước của đối số dòng lệnh. Sử dụng một forvòng lặp thay thế.

Nguồn gốc của vấn đề

Đây là một vấn đề hệ thống, liên quan đến execveARG_MAXliên tục. Có rất nhiều tài liệu về điều đó (xem người đàn ông hành quyết , wiki của debian ).

Về cơ bản, việc mở rộng tạo ra một lệnh (với các tham số của nó) vượt quá ARG_MAXgiới hạn. Trên kernel 2.6.23, giới hạn đã được đặt ở 128 kB. Hằng số này đã được tăng lên và bạn có thể nhận được giá trị của nó bằng cách thực hiện:

getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic

Giải pháp: Sử dụng forLoop

Sử dụng forvòng lặp như được khuyến nghị trên BashFAQ / 095 và không có giới hạn ngoại trừ dung lượng RAM / bộ nhớ:

Chạy khô để xác định nó sẽ xóa những gì bạn mong đợi:

for f in *.pdf; do echo rm "$f"; done

Và thực hiện nó:

for f in *.pdf; do rm "$f"; done

Ngoài ra, đây là một cách tiếp cận di động vì toàn cầu có hành vi mạnh mẽ và nhất quán giữa các hệ vỏ ( một phần của thông số POSIX ).

Lưu ý: Như đã lưu ý bởi một số ý kiến, điều này thực sự chậm hơn nhưng có thể duy trì nhiều hơn vì nó có thể điều chỉnh các kịch bản phức tạp hơn, ví dụ như người ta muốn làm nhiều hơn chỉ một hành động.

Giải pháp: Sử dụng find

Nếu bạn khăng khăng, bạn có thể sử dụng findnhưng thực sự không sử dụng xargs vì nó "nguy hiểm (bị hỏng, có thể khai thác, v.v.) khi đọc đầu vào không phân cách bằng NUL" :

find . -maxdepth 1 -name '*.pdf' -delete 

Sử dụng -maxdepth 1 ... -deletethay vì -exec rm {} +cho phép findthực hiện đơn giản các cuộc gọi hệ thống cần thiết mà không cần sử dụng quy trình bên ngoài, do đó nhanh hơn (nhờ nhận xét @chepner ).

Người giới thiệu


31
Câu trả lời tuyệt vời, đây là cách tất cả các câu hỏi SO nên được trả lời. Cảm ơn!
tham gia

1
+1 để đề cập đến forvòng lặp. Tôi đã từng sử dụng findtrước đây, nhưng tôi luôn tìm cách làm điều đó khi tôi quên các tùy chọn, v.v. forcó vẻ dễ nhớ hơn IMHO
Robert Dundon

3
Sử dụng nó như một for f in *; do rm "$f"; donecông việc quyến rũ
abdul qayyum

3
Các find -execgiải pháp có vẻ là MUCH nhanh hơn các forvòng lặp.
threeve

2
Năm năm sau tại 4.15.0 ( 4.15.0-1019-gcpchính xác) và giới hạn vẫn là 2097152. Thật thú vị, việc tìm kiếm ARG_MAX trên linux git repo cho kết quả hiển thị ARG_MAX ở mức 131702.
Matt M.

181

findcó một -deletehành động:

find . -maxdepth 1 -name '*.pdf' -delete

4
Điều này vẫn sẽ trả về "Danh sách đối số quá dài". Ít nhất là đối với tôi. Sử dụng xargs, theo câu trả lời của Dennis, hoạt động như dự định.
Sergio

7
Nghe có vẻ như một lỗi trong tìm kiếm.
ThiefMaster

3
@Sergio có cùng một vấn đề, nó được gây ra bởi các trích dẫn bị thiếu xung quanh mẫu tên.
Luxian

argh, tại sao một công cụ tìm kiếm công cụ thậm chí có một công tắc để xóa? Có thực sự chỉ là tôi thấy không cần thiết phải nói ít nhất và cũng nguy hiểm.
toán học

2
@mathreadler Nó giải quyết một thực tế là trường hợp sử dụng phổ biến -execlà loại bỏ một loạt các tệp. -exec rm {} +sẽ làm điều tương tự, nhưng vẫn yêu cầu bắt đầu ít nhất một quy trình bên ngoài. -deletecho phép findthực hiện đơn giản các cuộc gọi hệ thống cần thiết mà không cần sử dụng trình bao bọc bên ngoài.
chepner

21

Một câu trả lời khác là buộc xargsphải xử lý các lệnh theo lô. Ví dụ với deletecác tệp 100tại một thời điểm, cdvào thư mục và chạy này:

echo *.pdf | xargs -n 100 rm


4
Để xóa lệnh trong linux, đây có thể là một thảm họa nếu bạn là một kỹ sư và bạn đã gõ một lỗi, tôi tin rằng đó là 'an toàn nhất và tôi biết những gì đang xảy ra' là điều tốt nhất. Không phải thứ ưa thích mà nếu bạn bỏ lỡ gõ một dấu chấm sẽ cho phép công ty của bạn sụp đổ trong một phút.
Nhân tạo thông minh

1
Làm thế nào chúng ta có thể làm điều này mở rộng mặc định cho các lệnh nhất định? Có rất nhiều lệnh linux "chuẩn" trong đó có biết chúng có cần tất cả chúng cùng một lúc hay không (như "rm")
user1212212

1
Lưu ý rằng điều này chỉ hoạt động trong đó echolà một vỏ dựng sẵn. Nếu bạn kết thúc bằng cách sử dụng lệnh echo, bạn vẫn sẽ chạy vào giới hạn đối số chương trình.
Toby Speight

14

Hoặc bạn có thể thử:

find . -name '*.pdf' -exec rm -f {} \;

Điều này cũng xóa các tập tin từ thư mục con. Làm thế nào để ngăn chặn điều đó?
Vicky

@NikunjChauhan Thêm tùy chọn -maxdepth:find . -maxdepth 1 -name '*.pdf' -exec rm -f {} \;
Jon Lin

Tôi không thể chèn tùy chọn maxdepth
Vicky

Tùy chọn đó có thể là tùy chọn chỉ dành cho Linux, theo câu trả lời của @ Dennis, ở trên (câu trả lời được chọn).
jvriesem

12

Nếu bạn đang cố gắng xóa một số lượng rất lớn các tệp cùng một lúc (tôi đã xóa một thư mục có hơn 485.000 ngày hôm nay), có thể bạn sẽ gặp phải lỗi này:

/bin/rm: Argument list too long.

Vấn đề là khi bạn gõ một cái gì đó như rm -rf *, *nó được thay thế bằng một danh sách của tất cả các tệp phù hợp, như, rm -rf file1 file2 file3 file4 file4, v.v. Có một bộ nhớ tương đối nhỏ được phân bổ để lưu trữ danh sách các đối số này và nếu nó được lấp đầy, shell sẽ không thực thi chương trình.

Để giải quyết vấn đề này, rất nhiều người sẽ sử dụng lệnh find để tìm mọi tập tin và chuyển từng cái một cho lệnh của r r rách như thế này:

find . -type f -exec rm -v {} \;

Vấn đề của tôi là tôi cần xóa 500.000 tệp và nó đã diễn ra quá lâu.

Tôi tình cờ phát hiện ra một cách nhanh hơn để xóa các tập tin - lệnh của Google tìm kiếm có một lá cờ -delete nghén được xây dựng ngay trong! Đây là những gì tôi đã kết thúc bằng cách sử dụng:

find . -type f -delete

Sử dụng phương pháp này, tôi đã xóa các tệp với tốc độ khoảng 2000 tệp / giây - nhanh hơn nhiều!

Bạn cũng có thể hiển thị tên tệp khi bạn xóa chúng:

find . -type f -print -delete

Hoặc thậm chí hiển thị bao nhiêu tệp sẽ bị xóa, sau đó mất bao lâu để xóa chúng:

root@devel# ls -1 | wc -l && time find . -type f -delete
100000
real    0m3.660s
user    0m0.036s
sys     0m0.552s

Cảm ơn. Tôi đã làm sudo find . -type f -deleteđể xóa khoảng 485 nghìn tập tin và nó đã làm việc cho tôi. Mất khoảng 20 giây.
Nigel Alderton

11

bạn có thể thử điều này:

for f in *.pdf
do
  rm $f
done

EDIT: Nhận xét của ThiefMaster đề nghị tôi không tiết lộ thông lệ nguy hiểm như vậy với jedis của vỏ trẻ, vì vậy tôi sẽ thêm phiên bản "an toàn hơn" (vì mục đích bảo quản mọi thứ khi ai đó có tệp "-rf. ..Pdf")

echo "# Whooooo" > /tmp/dummy.sh
for f in '*.pdf'
do
   echo "rm -i $f" >> /tmp/dummy.sh
done

Sau khi chạy ở trên, chỉ cần mở tệp /tmp/dummy.sh trong fav của bạn. biên tập viên và kiểm tra từng dòng cho tên tệp nguy hiểm, nhận xét chúng nếu tìm thấy.

Sau đó sao chép tập lệnh dummy.sh trong thư mục làm việc của bạn và chạy nó.

Tất cả điều này vì lý do bảo mật.


5
Tôi nghĩ rằng điều này sẽ làm những điều thực sự tốt đẹp với một tập tin có tên ví dụ-rf .. .pdf
ThiefMaster

đúng vậy, nhưng nói chung khi được sử dụng trong shell, người phát hành lệnh "nên" đưa ra cái nhìn về những gì anh ta đang làm :). Trên thực tế tôi thích chuyển hướng đến một tập tin và sau đó kiểm tra từng hàng.
BigMike

2
Điều này không trích dẫn "$ f". Đó là những gì ThiefMaster đang nói. -rfđược ưu tiên hơn -i, vì vậy phiên bản thứ 2 của bạn sẽ không tốt hơn (không có kiểm tra thủ công). Và về cơ bản là vô dụng để xóa hàng loạt, vì nhắc nhở cho mọi tệp.
Peter Cordes

7

Bạn có thể sử dụng một mảng bash:

files=(*.pdf)
for((I=0;I<${#files[@]};I+=1000)); do
    rm -f "${files[@]:I:1000}"
done

Bằng cách này, nó sẽ xóa theo lô 1000 tệp mỗi bước.


2
Đối với một số lượng lớn các tệp, điều này dường như nhanh hơn đáng kể
James Tocknell

5

bạn có thể sử dụng lời khen này

find -name "*.pdf"  -delete

4

Lệnh rm có giới hạn các tệp mà bạn có thể loại bỏ đồng thời.

Một khả năng bạn có thể loại bỏ chúng bằng cách sử dụng nhiều lần lệnh rm dựa trên các mẫu tệp của bạn, như:

rm -f A*.pdf
rm -f B*.pdf
rm -f C*.pdf
...
rm -f *.pdf

Bạn cũng có thể loại bỏ chúng thông qua lệnh find :

find . -name "*.pdf" -exec rm {} \;

3
Không, rmkhông có giới hạn như vậy đối với số lượng tệp mà nó sẽ xử lý (ngoại trừ số lượng tệp argckhông thể lớn hơn INT_MAX). Đó là giới hạn của hạt nhân đối với kích thước tối đa của toàn bộ mảng đối số (đó là lý do tại sao độ dài của tên tệp là đáng kể).
Toby Speight

3

Nếu chúng là tên tệp có dấu cách hoặc ký tự đặc biệt, hãy sử dụng:

find -maxdepth 1 -name '*.pdf' -exec rm "{}" \;

Câu này tìm kiếm tất cả các tệp trong thư mục hiện tại (-maxdepth 1) với phần mở rộng pdf (-name '* .pdf'), và sau đó, xóa từng tệp (-exec rm "{}").

Biểu thức {} thay thế tên của tệp và "{}" đặt tên tệp là chuỗi, bao gồm khoảng trắng hoặc ký tự đặc biệt.


Mặc dù đoạn mã này có thể giải quyết câu hỏi, bao gồm giải thích về cách thứclý do giải quyết vấn đề này thực sự sẽ giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai, không chỉ là người hỏi bây giờ! Vui lòng chỉnh sửa câu trả lời của bạn để thêm giải thích và đưa ra dấu hiệu về những hạn chế và giả định được áp dụng.
Toby Speight

Toàn bộ vấn đề -execlà bạn không gọi vỏ. Các trích dẫn ở đây hoàn toàn không có gì hữu ích. (Họ ngăn chặn bất kỳ sự mở rộng ký tự đại diện và tách thẻ trên chuỗi trong vỏ nơi bạn gõ vào lệnh này, nhưng chuỗi {}không chứa bất kỳ khoảng trắng hoặc shell ký tự đại diện.)
tripleee

2

tôi đã phải đối mặt với cùng một vấn đề trong khi sao chép thư mục nguồn mẫu đến đích

thư mục nguồn có tập tin ~ 3 lakcs

tôi đã sử dụng cp với tùy chọn -r và nó hiệu quả với tôi

cp -r abc / def /

nó sẽ sao chép tất cả các tệp từ abc sang def mà không đưa ra cảnh báo về danh sách Đối số quá lâu


Tôi không biết tại sao ai đó đánh giá thấp điều này, mà thậm chí không bình luận về điều đó (chính sách đó, thưa các bạn!). Tôi cần phải xóa tất cả các tệp trong một thư mục (câu hỏi không phải là cụ thể về các tệp PDF, làm phiền bạn) và vì thế, thủ thuật này hoạt động tốt, cuối cùng tất cả mọi người phải làm là tạo lại thư mục đã bị xóa khi Tôi đã sử dụng `rm -R / path / to / thư mục".
Thomas Tempelmann

1
Nó hoạt động vì trong trường hợp của OP, anh ta đã sử dụng *, mở rộng ra một danh sách lớn .pdf, việc đưa ra một thư mục sẽ khiến điều này được xử lý nội bộ, do đó, không phải xử lý vấn đề của OP. Tôi nghĩ rằng nó đã bị hạ thấp vì lý do đó. OP có thể không sử dụng được nếu anh ta có thư mục lồng nhau hoặc các tệp khác (không phải pdf) trong thư mục của mình
Alvein

2

Cũng thử làm điều này Nếu bạn muốn xóa các tệp / thư mục 30/90 ngày (+) hoặc dưới 30/90 (-) ngày thì bạn có thể sử dụng các lệnh ex bên dưới

Ví dụ: Trong 90 ngày loại trừ ở trên sau khi xóa 90 ngày tệp / thư mục, có nghĩa là 91,92 .... 100 ngày

find <path> -type f -mtime +90 -exec rm -rf {} \;

Ví dụ: Chỉ với các tệp 30 ngày gần nhất mà bạn muốn xóa, sau đó sử dụng lệnh bên dưới (-)

find <path> -type f -mtime -30 -exec rm -rf {} \;

Nếu bạn muốn giz các tệp trong hơn 2 ngày tệp

find <path> -type f -mtime +2 -exec gzip {} \;

Nếu bạn chỉ muốn xem các tập tin / thư mục từ một tháng qua. Ví dụ:

find <path> -type f -mtime -30 -exec ls -lrt {} \;

Trên 30 ngày chỉ sau đó liệt kê các tệp / thư mục Ex:

find <path> -type f -mtime +30 -exec ls -lrt {} \;

find /opt/app/logs -type f -mtime +30 -exec ls -lrt {} \;

2

Tôi ngạc nhiên không có ulimitcâu trả lời ở đây. Mỗi khi tôi gặp vấn đề này, tôi kết thúc ở đây hoặc ở đây . Tôi hiểu giải pháp này có những hạn chế nhưng ulimit -s 65536dường như thường làm thủ thuật cho tôi.


1

Tôi gặp vấn đề tương tự với một thư mục chứa đầy hình ảnh tạm thời đang phát triển từng ngày và lệnh này đã giúp tôi xóa thư mục

find . -name "*.png" -mtime +50 -exec rm {} \;

Sự khác biệt với các lệnh khác là tham số mtime sẽ chỉ mất các tệp cũ hơn X ngày (trong ví dụ 50 ngày)

Sử dụng nhiều lần, giảm trên mỗi lần thực hiện phạm vi ngày, tôi có thể xóa tất cả các tệp không cần thiết


1

Tôi chỉ biết một cách xung quanh này. Ý tưởng là xuất danh sách các tệp pdf mà bạn có thành một tệp. Sau đó chia tập tin đó thành nhiều phần. Sau đó loại bỏ các tập tin pdf được liệt kê trong mỗi phần.

ls | grep .pdf > list.txt
wc -l list.txt

wc -l là để đếm có bao nhiêu dòng list.txt chứa. Khi bạn có ý tưởng về thời gian là bao lâu, bạn có thể quyết định chia nó thành một nửa, một hoặc một cái gì đó. Sử dụng lệnh split -l Ví dụ: chia nó thành 600 dòng mỗi dòng.

split -l 600 list.txt

điều này sẽ tạo ra một vài tập tin có tên xaa, xab, xac, v.v. tùy thuộc vào cách bạn chia nó. Bây giờ để "nhập" từng danh sách trong các tệp đó vào lệnh rm, hãy sử dụng:

rm $(<xaa)
rm $(<xab)
rm $(<xac)

Xin lỗi vì tiếng Anh của tôi không tốt.


5
Nếu bạn có một tệp có tên pdf_format_sucks.docxthì nó cũng sẽ bị xóa ... ;-) Bạn nên sử dụng biểu thức chính quy đúng và chính xác khi grepping cho các tệp pdf.
FooF

1
Tốt hơn, nhưng still_pdf_format_sucks.docxsẽ bị xóa. Dấu chấm .trong ".pdf"biểu thức chính quy phù hợp với bất kỳ ký tự nào. Tôi sẽ đề nghị "[.]pdf$"thay vì .pdf.
FooF

1

Tôi đã gặp vấn đề này một vài lần. Nhiều giải pháp sẽ chạy rmlệnh cho từng tệp riêng lẻ cần xóa. Điều này rất không hiệu quả:

find . -name "*.pdf" -print0 | xargs -0 rm -rf

Cuối cùng tôi đã viết một kịch bản python để xóa các tệp dựa trên 4 ký tự đầu tiên trong tên tệp:

import os
filedir = '/tmp/' #The directory you wish to run rm on 
filelist = (os.listdir(filedir)) #gets listing of all files in the specified dir
newlist = [] #Makes a blank list named newlist
for i in filelist: 
    if str((i)[:4]) not in newlist: #This makes sure that the elements are unique for newlist
        newlist.append((i)[:4]) #This takes only the first 4 charcters of the folder/filename and appends it to newlist
for i in newlist:
    if 'tmp' in i:  #If statment to look for tmp in the filename/dirname
        print ('Running command rm -rf '+str(filedir)+str(i)+'* : File Count: '+str(len(os.listdir(filedir)))) #Prints the command to be run and a total file count
        os.system('rm -rf '+str(filedir)+str(i)+'*') #Actual shell command
print ('DONE')

Điều này làm việc rất tốt cho tôi. Tôi đã có thể xóa hơn 2 triệu tệp tạm thời trong một thư mục trong khoảng 15 phút. Tôi đã nhận xét tar ra khỏi một chút mã để bất kỳ ai có kiến ​​thức tối thiểu đến trăn có thể thao túng mã này.


1

Và một số khác:

cd  /path/to/pdf
printf "%s\0" *.[Pp][Dd][Ff] | xargs -0 rm

printflà một vỏ được tích hợp sẵn, và theo như tôi biết thì nó luôn như vậy. Bây giờ được cho rằng đó printfkhông phải là lệnh shell (mà là nội dung), nó không phải chịu argument list too long ..."lỗi nghiêm trọng".

Vì vậy, chúng ta có thể sử dụng nó một cách an toàn với các mẫu toàn cầu shell *.[Pp][Dd][Ff], sau đó chúng ta chuyển đầu ra của nó để loại bỏ rmlệnh ( ) xargs, để đảm bảo nó phù hợp với đủ tên tệp trong dòng lệnh để không bị lỗi rmlệnh, đó là shell chỉ huy.

Các \0trong printfđóng vai trò như một tách null cho tên tập tin Mà sau đó được xử lý bởi xargslệnh, sử dụng nó ( -0) như là một dấu phân cách, vì vậy rmkhông thất bại khi có không gian màu trắng hoặc ký tự đặc biệt khác trong tên tập tin.


1
Mặc dù đoạn mã này có thể giải quyết câu hỏi, bao gồm giải thích về cách thứclý do giải quyết vấn đề này thực sự sẽ giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai, không chỉ là người hỏi bây giờ! Vui lòng chỉnh sửa câu trả lời của bạn để thêm giải thích và đưa ra dấu hiệu về những hạn chế và giả định được áp dụng.
Toby Speight

Đặc biệt, nếu printfkhông phải là vỏ dựng sẵn, nó sẽ chịu cùng giới hạn.
Toby Speight

0

Bạn có thể tạo thư mục tạm thời, di chuyển tất cả các tệp và thư mục con bạn muốn giữ vào thư mục tạm thời sau đó xóa thư mục cũ và đổi tên thư mục tạm thời sang thư mục cũ thử ví dụ này cho đến khi bạn tự tin thực hiện trực tiếp:

mkdir testit
cd testit
mkdir big_folder tmp_folder
touch big_folder/file1.pdf
touch big_folder/file2.pdf
mv big_folder/file1,pdf tmp_folder/
rm -r big_folder
mv tmp_folder big_folder

những rm -r big_foldersẽ loại bỏ tất cả các file trong big_folderdù có bao nhiêu. Bạn phải cực kỳ cẩn thận, trước tiên bạn có tất cả các tệp / thư mục bạn muốn giữ, trong trường hợp này làfile1.pdf


0

Để xóa tất cả *.pdftrong một thư mục/path/to/dir_with_pdf_files/

mkdir empty_dir        # Create temp empty dir

rsync -avh --delete --include '*.pdf' empty_dir/ /path/to/dir_with_pdf_files/

Để xóa các tệp cụ thể thông qua rsyncsử dụng ký tự đại diện có lẽ là giải pháp nhanh nhất trong trường hợp bạn có hàng triệu tệp. Và nó sẽ xử lý lỗi bạn nhận được.


(Bước tùy chọn): CHẠY KHÔ. Để kiểm tra những gì sẽ bị xóa mà không cần xóa. `

rsync -avhn --delete --include '*.pdf' empty_dir/ /path/to/dir_with_pdf_files/

. . .

Nhấp vào mẹo và thủ thuật rsync để biết thêm hack rsync


0

Tôi thấy rằng đối với các danh sách tệp cực lớn (> 1e6), những câu trả lời này quá chậm. Đây là một giải pháp sử dụng xử lý song song trong python. Tôi biết, tôi biết, đây không phải là linux ... nhưng không có gì khác ở đây hoạt động.

(Điều này giúp tôi tiết kiệm hàng giờ)

# delete files
import os as os
import glob
import multiprocessing as mp

directory = r'your/directory'
os.chdir(directory)


files_names = [i for i in glob.glob('*.{}'.format('pdf'))]

# report errors from pool

def callback_error(result):
    print('error', result)

# delete file using system command
def delete_files(file_name):
     os.system('rm -rf ' + file_name)

pool = mp.Pool(12)  
# or use pool = mp.Pool(mp.cpu_count())


if __name__ == '__main__':
    for file_name in files_names:
        print(file_name)
        pool.apply_async(delete_files,[file_name], error_callback=callback_error)

0

Tôi đã phải đối mặt với một vấn đề tương tự khi có hàng triệu tệp nhật ký vô dụng được tạo bởi một ứng dụng chứa đầy tất cả các nút. Tôi đã dùng đến "định vị", đưa tất cả các tệp "nằm" vào một tệp văn bản và sau đó loại bỏ từng tệp một. Mất một lúc nhưng đã làm được việc!


Điều này khá mơ hồ và yêu cầu bạn phải cài đặt locatelại khi bạn vẫn còn chỗ trên đĩa.
tripleee

-2

Phiên bản an toàn hơn một chút so với sử dụng xargs, cũng không đệ quy: ls -p | grep -v '/$' | grep '\.pdf$' | while read file; do rm "$file"; done

Lọc các thư mục của chúng tôi ở đây là một chút không cần thiết vì dù sao 'rm' sẽ không xóa nó và nó có thể được gỡ bỏ để đơn giản, nhưng tại sao chạy một cái gì đó chắc chắn sẽ trả về lỗi?


3
Điều này hoàn toàn không an toàn và không hoạt động với tên tệp có dòng mới trong đó, để chỉ ra một trường hợp góc rõ ràng. Phân tích cú phápls là một antipotype phổ biến chắc chắn nên tránh và thêm một số lỗi bổ sung ở đây. Chỉ grep | greplà không thanh lịch.
tripleee

Dù sao, nó không giống như đây là một vấn đề mới và kỳ lạ đòi hỏi một giải pháp phức tạp. Các câu trả lời findlà tốt, và tài liệu tốt ở đây và ở nơi khác. Xem ví dụ: mywiki.wooledge.org để biết thêm về chủ đề này và các chủ đề liên quan.
tripleee

-2

Sử dụng GNUallel ( sudo apt install parallel) là siêu dễ dàng

Nó chạy các lệnh đa luồng trong đó '{}' là đối số được truyền

Ví dụ

ls /tmp/myfiles* | parallel 'rm {}'


Tôi không biết, nhưng tôi đoán nó bởi vì việc truyền lstrực tiếp đầu ra cho các lệnh khác là một phản mẫu nguy hiểm - và thực tế là việc mở rộng ký tự đại diện sẽ gây ra lỗi tương tự khi thực hiện lsnhư đã có kinh nghiệm trong rmlệnh ban đầu .
Toby Speight

Đối với bối cảnh trên đó, xem ParsingLs . Và parallellàm cho một số người thích tránh sự phức tạp khó chịu - nếu bạn nhìn dưới mui xe, nó khá mờ. Xem chủ đề danh sách gửi thư tạilists.gnu.org/archive/html/orms-abul/2015-05/msg00005.html giữa Stephane (một trong những greybeards Unix & Linux StackExchange ) và Ole Tange (tác giả của Parallel). xargs -Pcũng làm tê liệt, nhưng nó thực hiện theo cách đơn giản, gọn gàng hơn với ít bộ phận chuyển động hơn, khiến cho hành vi của nó dễ dàng hơn để dự đoán và lý do.
Charles Duffy

-2

Để xóa 100 tệp đầu tiên:

rm -rf 'ls | đầu -100 '


2
Nguy hiểm (hoặc sẽ là nếu bạn sử dụng backquote như dự định rõ ràng) - nếu bất kỳ tên tệp nào chứa siêu ký tự shell, bao gồm khoảng trắng, thì kết quả sẽ không như bạn dự định.
Toby Speight

-5

Các tùy chọn dưới đây có vẻ đơn giản cho vấn đề này. Tôi đã nhận được thông tin này từ một số chủ đề khác nhưng nó đã giúp tôi.

for file in /usr/op/data/Software/temp/application/openpages-storage/*; do
    cp "$file" /opt/sw/op-storage/
done

Chỉ cần chạy một lệnh trên và nó sẽ thực hiện nhiệm vụ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.