Zbyt długi błąd listy argumentów dla komend rm, cp, mv

629

Mam kilkaset plików PDF w katalogu w systemie UNIX. Nazwy plików PDF są naprawdę długie (około 60 znaków).

Kiedy próbuję usunąć wszystkie pliki PDF razem za pomocą następującego polecenia:

rm -f *.pdf

Otrzymuję następujący błąd:

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

Jakie jest rozwiązanie tego błędu? Czy ten błąd występuje na mvi cppoleceń, jak również? Jeśli tak, jak rozwiązać te polecenia?

Vicky
źródło
21
Ten link może Ci się przydać
another.anon.coward
1
Może to być również istotne http://mywiki.wooledge.org/BashFAQ/095
Lorenzo Belli
4
@jww: I tak długo myślałem, że bash należy do „narzędzi programowych powszechnie używanych przez programistów” - kategorii, której pytania można tutaj zadać!
Vicky,
@Nik - Dodanie „... w skrypcie” nie jest przekonujące. Gdy problem zostanie zredukowany do minimalnego, pełnego i weryfikowalnego przykładu , będzie to tylko pytanie, jak uruchomić polecenie. Przepraszam, że brakuje mi czegoś oczywistego.
jww

Odpowiedzi:

876

Powodem tego jest fakt, że bash rozszerza gwiazdkę do każdego pasującego pliku, tworząc bardzo długą linię poleceń.

Spróbuj tego:

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

Ostrzeżenie: jest to wyszukiwanie rekurencyjne, które również znajdzie (i usunie) pliki w podkatalogach. Dołączać -fdo polecenia rm tylko jeśli jesteś pewien, że nie chcesz potwierdzenia.

Możesz wykonać następujące czynności, aby polecenie nie było rekurencyjne:

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

Inną opcją jest użycie -deleteflagi find :

find . -name "*.pdf" -delete
DPlusV
źródło
7
Nie, w xargsszczególności dzieli listę i wydaje w razie potrzeby kilka poleceń.
tripleee
7
@Dennis: -maxdepth 1musi być pierwszym argumentem po ścieżce.
Barton Chittenden,
54
Find ma -deleteflagę do usuwania znalezionych plików, a nawet jeśli nie, nadal uważane byłoby za lepszą praktykę -execwykonywania rm, zamiast wywoływania xargs (które są teraz 3 procesami i potokiem zamiast jednego procesu z -deletelub 2 procesy z -exec).
scragar
3
@ ÉdouardLopez ... Ale to odczytuje dane rozdzielane wartościami NULL. A całość dangerous (broken, exploitable, etc.)jest dość niedorzeczna. Niewątpliwie należy zachować ostrożność podczas korzystania xargs, ale nie jest to do końca eval/evil.
Przywróć Monikę, proszę
4
@scragar W przypadku -execwywoływania rmliczba procesów będzie wynosić 1 + liczba plików, chociaż liczba współbieżnych procesów z tego może wynosić 2 (być może funkcja find wykonałaby procesy rm jednocześnie). Liczba używanych procesów xargszostałaby radykalnie zmniejszona do 2 + n, gdzie n jest pewną liczbą procesów mniejszą niż liczba plików (powiedzmy liczbę plików / 10, chociaż prawdopodobnie więcej w zależności od długości ścieżek). Zakładając, że find wykonuje usuwanie bezpośrednio, użycie -deletepowinno być jedynym procesem, który zostałby wywołany.
neuralmer
396

tl; dr

Jest to ograniczenie jądra dotyczące wielkości argumentu wiersza poleceń. forZamiast tego użyj pętli.

Geneza problemu

Jest to problem systemowy, związany execvei ARG_MAXstały. Jest mnóstwo dokumentacji na ten temat (patrz man execve , wiki debiana ).

Zasadniczo rozszerzenie tworzy polecenie (z jego parametrami), które przekracza ARG_MAXlimit. W jądrze 2.6.23limit został ustawiony na 128 kB. Ta stała została zwiększona i możesz uzyskać jej wartość, wykonując:

getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic

Rozwiązanie: za pomocą forpętli

Użyj forpętli, jak jest to zalecane w BashFAQ / 095, i nie ma limitu, z wyjątkiem pamięci RAM / pamięci:

Uruchom na sucho, aby upewnić się, że usunie to, czego oczekujesz:

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

I wykonaj to:

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

Jest to również podejście przenośne, ponieważ glob ma silne i spójne zachowanie wśród powłok ( część specyfikacji POSIX ).

Uwaga: Jak zauważono w kilku komentarzach, jest to rzeczywiście wolniejsze, ale łatwiejsze w utrzymaniu, ponieważ może dostosować bardziej złożone scenariusze, np. Gdy chce się wykonać więcej niż jedną akcję.

Rozwiązanie: za pomocą find

Jeśli nalegasz, możesz używać, findale tak naprawdę nie używać xargs, ponieważ „jest niebezpieczny (uszkodzony, nadający się do wykorzystania itp.) Podczas odczytywania danych nie rozdzielonych znakiem NUL” :

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

Użycie -maxdepth 1 ... -deletezamiast -exec rm {} +pozwala findpo prostu samodzielnie wykonać wymagane wywołania systemowe bez użycia zewnętrznego procesu, a tym samym szybciej (dzięki komentarzowi @chepner ).

Bibliografia

Édouard Lopez
źródło
31
Świetna odpowiedź, w ten sposób należy odpowiedzieć na wszystkie SO pytania. Dzięki!
tommed
1
+1 za wzmiankę o forpętli. Używałem już findwcześniej, ale zawsze szukam, jak to zrobić, ponieważ cały czas zapominam o opcjach itp. forwydaje się łatwiejsze do zapamiętania IMHO
Robert Dundon
3
for f in *; do rm "$f"; done
Użyłem
3
find -execRozwiązaniem wydaje się być o wiele szybciej niż forpętli.
threeve
2
Pięć lat później o 4.15.0 ( 4.15.0-1019-gcpa dokładniej), a limit nadal wynosi 2097152. Co ciekawe, wyszukiwanie ARG_MAX na linux git repo daje wynik pokazujący ARG_MAX na 131702.
Matt M.
181

findma -deletedziałanie:

find . -maxdepth 1 -name '*.pdf' -delete
ThiefMaster
źródło
4
To nadal zwróciłoby „Lista argumentów za długa”. Przynajmniej dla mnie tak. Korzystanie z xargsodpowiedzi Dennisa działa zgodnie z przeznaczeniem.
Sergio
7
To brzmi jak błąd w znalezieniu.
ThiefMaster
3
@Sergio miał ten sam problem, był spowodowany brakującymi cudzysłowami wokół wzorca nazwy.
Luxian
argh, dlaczego narzędzie do wyszukiwania rzeczy ma nawet przełącznik do usuwania? czy to naprawdę tylko ja uważam, że mówienie co najmniej, a także niebezpieczne, jest niepotrzebne.
matematyk
2
@ matreadler Odnosi się do faktu, że częstym przypadkiem użycia -execjest usunięcie kilku plików. -exec rm {} +zrobiłby to samo, ale nadal wymaga uruchomienia co najmniej jednego procesu zewnętrznego. -deletepozwala findpo prostu samodzielnie wykonać wymagane wywołania systemowe bez użycia zewnętrznego opakowania.
chepner,
21

Inną odpowiedzią jest wymuszenie xargsprzetwarzania poleceń w partiach. Na przykład do deleteplików 100na raz, cddo katalogu i uruchom to:

echo *.pdf | xargs -n 100 rm

portforwardpodcast
źródło
4
Jeśli chodzi o usunięcie polecenia w systemie Linux, co może być katastrofą, jeśli jesteś inżynierem i popełniłeś błąd, uważam, że jest to „najbezpieczniejsze i wiem, co się dzieje” jest najlepsze. Nie wymyślne rzeczy, które jeśli pominiesz kropkę, pozwolą Twojej firmie załamać się w ciągu minuty.
Sztuczna
1
Jak możemy uczynić to domyślnym rozszerzeniem dla niektórych poleceń? Istnieje wiele „standardowych” poleceń Linuksa, o których wiadomo, że potrzebują ich wszystkie naraz (np. „
Rm
1
Zauważ, że działa to tylko tam, gdzie echojest wbudowana powłoka. Jeśli użyjesz polecenia echo, nadal będziesz mieć do czynienia z limitem argumentów programu.
Toby Speight,
14

Lub możesz spróbować:

find . -name '*.pdf' -exec rm -f {} \;
Jon Lin
źródło
Spowoduje to również usunięcie plików z podkatalogów. Jak temu zapobiec?
Vicky,
@NikunjChauhan Dodaj -maxdepth opcja:find . -maxdepth 1 -name '*.pdf' -exec rm -f {} \;
Jon Lin
Nie jestem w stanie wstawić opcji maxdepth
Vicky,
Ta opcja może być opcją tylko dla Linuksa, zgodnie z odpowiedzią @ Dennisa powyżej (wybrana odpowiedź).
jvriesem
12

Jeśli próbujesz usunąć bardzo dużą liczbę plików jednocześnie (dzisiaj usunąłem katalog z 485,000+), prawdopodobnie wystąpi ten błąd:

/bin/rm: Argument list too long.

Problem polega na tym, że gdy coś wpiszesz rm -rf *, *zostanie zastąpione listą każdego pasującego pliku, na przykład „rm -rf plik1 plik2 plik3 plik4” i tak dalej. Do przechowywania tej listy argumentów przydzielono stosunkowo mały bufor pamięci, a jeśli zostanie ona zapełniona, powłoka nie uruchomi programu.

Aby obejść ten problem, wiele osób użyje polecenia find do znalezienia każdego pliku i przekaże je pojedynczo do polecenia „rm” w następujący sposób:

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

Mój problem polega na tym, że musiałem usunąć 500 000 plików i trwało to zbyt długo.

Natknąłem się na znacznie szybszy sposób usuwania plików - polecenie „find” ma wbudowaną flagę „-delete”! Oto, co wykorzystałem:

find . -type f -delete

Korzystając z tej metody, usuwałem pliki z prędkością około 2000 plików na sekundę - znacznie szybciej!

Możesz także wyświetlać nazwy plików podczas ich usuwania:

find . -type f -print -delete

… Lub nawet pokaż, ile plików zostanie usuniętych, a następnie określ, ile czasu zajmuje ich usunięcie:

root@devel# ls -1 | wc -l && time find . -type f -delete
100000
real    0m3.660s
user    0m0.036s
sys     0m0.552s
Bibin Joseph
źródło
Dzięki. Zrobiłem sudo find . -type f -deleteusunąć około 485 tysięcy plików i pracował dla mnie. Zajęło to około 20 sekund.
Nigel Alderton
11

możesz spróbować:

for f in *.pdf
do
  rm $f
done

EDYCJA: Komentarz ThiefMaster sugeruje, żebym nie ujawniał tak niebezpiecznej praktyki jedisom młodego shella, dlatego dodam bardziej „bezpieczniejszą” wersję (w celu zachowania rzeczy, gdy ktoś ma plik „-rf. ..Pdf”)

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

Po uruchomieniu powyższego, po prostu otwórz plik /tmp/dummy.sh w swoim ulubionym. edytor i sprawdzaj każdą linię pod kątem niebezpiecznych nazw plików, komentując je, jeśli zostaną znalezione.

Następnie skopiuj skrypt dummy.sh do działającego katalogu i uruchom go.

Wszystko to ze względów bezpieczeństwa.

BigMike
źródło
5
Myślę, że przydałoby się to naprawdę miłe rzeczy z plikiem o nazwie np.-rf .. .pdf
ThiefMaster
tak, ale ogólnie, gdy jest używany w powłoce, wydawca polecenia „powinien” rzucić okiem na to, co robi :). Właściwie wolę przekierować do pliku, a następnie sprawdzam każdy pojedynczy wiersz.
BigMike,
2
To nie cytuje „$ f”. O tym mówił ThiefMaster. -rfma pierwszeństwo przed -idrugą wersją, więc druga wersja nie jest lepsza (bez ręcznej kontroli). I jest w zasadzie bezużyteczny do masowego usuwania, ponieważ monituje o każdy plik.
Peter Cordes
7

Możesz użyć tablicy bash:

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

W ten sposób zostanie skasowany w partiach po 1000 plików na krok.

danjperron
źródło
2
W przypadku dużej liczby plików wydaje się to znacznie szybsze
James Tocknell
5

możesz użyć tego polecenia

find -name "*.pdf"  -delete
Sarath Ak
źródło
4

Polecenie rm ma ograniczenie plików, które można jednocześnie usuwać.

Jedną z możliwości można je usunąć przy użyciu polecenia rm wielokrotnie w oparciu o wzorce plików, na przykład:

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

Możesz je również usunąć za pomocą polecenia find :

find . -name "*.pdf" -exec rm {} \;
Fabio Farath
źródło
3
Nie, rmnie ma takiego limitu liczby plików, które będzie przetwarzać (poza tym, że argcnie może być większy niż INT_MAX). Jest to ograniczenie jądra do maksymalnego rozmiaru całej tablicy argumentów (dlatego długość nazw plików jest znacząca).
Toby Speight,
3

Jeśli są to nazwy plików ze spacjami lub znakami specjalnymi, użyj:

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

To zdanie przeszukuje wszystkie pliki w bieżącym katalogu (-maxdepth 1) z rozszerzeniem pdf (-name „* .pdf”), a następnie usuwa każdy z nich (-exec rm "{}").

Wyrażenie {} zastępuje nazwę pliku i „{}” ustawia nazwę pliku jako ciąg znaków, zawierający spacje lub znaki specjalne.

Alejandro Salamanca Mazuelo
źródło
Chociaż ten fragment kodu może rozwiązać pytanie, w tym wyjaśnienie, w jaki sposób i dlaczego to rozwiązuje, problem naprawdę pomógłby poprawić jakość twojego postu. Pamiętaj, że odpowiadasz na pytanie dla czytelników w przyszłości, nie tylko dla osoby zadającej teraz pytanie! Proszę edytować swoje odpowiedzi, aby dodać wyjaśnienie, i dać wskazówkę co zastosować ograniczenia i założenia.
Toby Speight,
Chodzi o -execto, że nie wywołujesz powłoki. Cytaty tutaj absolutnie nic pożytecznego. (Zapobiegają ekspansji symboli wieloznacznych i dzieleniu tokenów na łańcuchu w powłoce, w której wpisujesz to polecenie, ale łańcuch {}nie zawiera żadnych białych znaków ani znaków wieloznacznych powłoki.)
tripleee 14.04.19
2

napotkałem ten sam problem podczas kopiowania katalogu źródłowego formularza do miejsca docelowego

katalog źródłowy miał pliki ~ 3 lakcs

użyłem cp z opcją -r i to zadziałało dla mnie

cp -r abc / def /

skopiuje wszystkie pliki z abc do def bez zbyt długiego ostrzeżenia o liście argumentów

użytkownik3405020
źródło
Nie wiem, dlaczego ktoś głosował za tym, nawet nie komentując tego (taka polityka, ludzie!). Musiałem usunąć wszystkie pliki w folderze (pytanie nie dotyczy konkretnie plików PDF, pamiętaj), a do tego ta sztuczka działa dobrze, wszystko, co musisz zrobić, to odtworzyć folder, który został usunięty, gdy Użyłem `rm -R / path / to / folder".
Thomas Tempelmann
1
Działa, ponieważ w przypadku OP używał *, który rozwinął się do ogromnej listy plików .pdf, podanie katalogu spowoduje, że będzie to traktowane wewnętrznie, a zatem nie będzie musiał zajmować się problemem OP. Myślę, że z tego powodu został odrzucony. Może nie być przydatny dla OP, jeśli zagnieździł katalog lub inne pliki (nie pdf) w swoim katalogu
Alvein
2

Wypróbuj to także Jeśli chcesz usunąć pliki / foldery powyżej 30/90 dni (+) lub poniżej 30/90 dni (-) dni, możesz użyć poniższych poleceń ex

Np .: W przypadku 90 dni wykluczone powyżej po usunięciu plików / folderów w ciągu 90 dni, oznacza to 91,92 .... 100 dni

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

Przykład: w przypadku najnowszych plików 30-dniowych, które chcesz usunąć, użyj poniższego polecenia (-)

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

Jeśli chcesz odłożyć pliki na więcej niż 2 dni

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

Jeśli chcesz zobaczyć pliki / foldery tylko z ostatniego miesiąca. Dawny:

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

Ponad 30 dni więcej niż tylko lista plików / folderów Np .:

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

find /opt/app/logs -type f -mtime +30 -exec ls -lrt {} \;
radża
źródło
2

Dziwię się, że nie ma ulimittu odpowiedzi. Za każdym razem, gdy mam ten problem, kończę tutaj lub tutaj . Rozumiem, że to rozwiązanie ma ograniczenia, ale ulimit -s 65536wydaje się, że często robi to dla mnie.

dps
źródło
1

Miałem ten sam problem z folderem pełnym tymczasowych obrazów, który rozwijał się z dnia na dzień, a to polecenie pomogło mi wyczyścić folder

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

Różnica w stosunku do innych poleceń to parametr mtime, który zajmie tylko pliki starsze niż X dni (w przykładzie 50 dni)

Używając tego wielokrotnie, zmniejszając się przy każdym wykonaniu zakresu dziennego, byłem w stanie usunąć wszystkie niepotrzebne pliki

Brugolo
źródło
1

Znam tylko sposób na obejście tego. Chodzi o to, aby wyeksportować tę listę plików pdf, które masz do pliku. Następnie podziel ten plik na kilka części. Następnie usuń pliki pdf wymienione w każdej części.

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

wc -l zlicza, ile linii zawiera list.txt. Kiedy masz pojęcie, jak długo to trwa, możesz zdecydować o podzieleniu go na pół, czwarte lub coś takiego. Używanie polecenia split -l Na przykład podziel go na 600 linii każdy.

split -l 600 list.txt

spowoduje to utworzenie kilku plików o nazwach xaa, xab, xac i tak dalej, zależnie od sposobu podziału. Teraz, aby „zaimportować” każdą listę z tego pliku do polecenia rm, użyj tego:

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

Przepraszam za mój zły angielski.

thai_phan
źródło
5
Jeśli masz plik o nazwie, pdf_format_sucks.docxzostanie on również usunięty ... ;-) Powinieneś używać właściwego i dokładnego wyrażenia regularnego podczas wyszukiwania plików pdf.
FooF
1
Lepiej, ale still_pdf_format_sucks.docxzostaną usunięte. Kropka .w ".pdf"wyrażeniu regularnym pasuje do dowolnego znaku. Sugerowałbym "[.]pdf$"zamiast .pdf.
FooF
1

Kilka razy spotkałem się z tym problemem. Wiele rozwiązań uruchamia rmpolecenie dla każdego pliku, który należy usunąć. Jest to bardzo nieefektywne:

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

Skończyło się na tym, że napisałem skrypt Pythona, aby usunąć pliki na podstawie pierwszych 4 znaków w nazwie pliku:

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')

To działało dla mnie bardzo dobrze. Udało mi się usunąć ponad 2 miliony plików tymczasowych w folderze w około 15 minut. Skomentowałem smołę z odrobiny kodu, aby każdy, kto ma minimalną lub żadną znajomość języka Python, mógł manipulować tym kodem.

Pedro Montero
źródło
1

I kolejny:

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

printfjest wbudowaną powłoką i, o ile wiem, zawsze była taka. Biorąc pod uwagę, że printfnie jest to polecenie powłoki (ale wbudowane), nie podlega „argument list too long ... błąd krytyczny.

Możemy więc bezpiecznie używać go z wzorcami globowania powłoki, takimi jak *.[Pp][Dd][Ff], następnie przesyłamy dane wyjściowe do polecenia remove ( rm), przez xargsco upewnia się, że pasuje ono do wystarczającej liczby nazw plików w wierszu poleceń, aby nie zawieść rmpolecenia, które jest powłoką Komenda.

\0W printfpełni rolę separatora null dla nazw plików wich są następnie przetwarzane przez xargspolecenia, używając go ( -0) jako separatora, więc rmnie zawieść, gdy istnieje spacji lub innych znaków specjalnych w nazwach plików.

lind
źródło
1
Chociaż ten fragment kodu może rozwiązać pytanie, w tym wyjaśnienie, w jaki sposób i dlaczego to rozwiązuje, problem naprawdę pomógłby poprawić jakość twojego postu. Pamiętaj, że odpowiadasz na pytanie dla czytelników w przyszłości, nie tylko dla osoby zadającej teraz pytanie! Proszę edytować swoje odpowiedzi, aby dodać wyjaśnienie, i dać wskazówkę co zastosować ograniczenia i założenia.
Toby Speight,
W szczególności, jeśli printfnie jest wbudowana powłoka, będzie podlegać tym samym ograniczeniom.
Toby Speight,
0

Możesz utworzyć folder tymczasowy, przenieść wszystkie pliki i podfoldery, które chcesz zachować, do folderu tymczasowego, a następnie usunąć stary folder i zmienić nazwę folderu tymczasowego na stary folder. Wypróbuj ten przykład, dopóki nie upewnisz się, że możesz to zrobić na żywo:

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

rm -r big_folderusunie wszystkie pliki w big_foldernieważne ile. Musisz tylko bardzo uważać, aby najpierw mieć wszystkie pliki / foldery, które chcesz zachować, w tym przypadku tak byłofile1.pdf

Keithhn
źródło
0

Aby usunąć wszystko *.pdf z katalogu/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/

Usuwanie określonych plików za rsyncpomocą symboli wieloznacznych jest prawdopodobnie najszybszym rozwiązaniem w przypadku milionów plików. I zajmie się błędem, który otrzymujesz.


(Krok opcjonalny): OSUSZANIE. Aby sprawdzić, co zostanie usunięte bez usuwania. `

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

. . .

Kliknij porady i wskazówki dotyczące rsync, aby uzyskać więcej hacków rsync

Raman Kathpalia
źródło
0

Odkryłem, że w przypadku bardzo dużych list plików (> 1e6) odpowiedzi te były zbyt wolne. Oto rozwiązanie wykorzystujące równoległe przetwarzanie w Pythonie. Wiem, wiem, to nie jest Linux ... ale nic innego tu nie działało.

(Oszczędzało mi to godzin)

# 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)
mmann1123
źródło
0

Podobny problem napotkałem, gdy w aplikacji wypełniającej wszystkie i-węzły były miliony bezużytecznych plików dziennika. Uciekłem się do „zlokalizowania”, umieściłem wszystkie pliki „zlokalizowane” d w pliku tekstowym, a następnie usunąłem je jeden po drugim. Trochę to zajęło, ale wykonałem robotę!

asatsi
źródło
Jest to dość niejasne i wymaga ponownej instalacji, locategdy wciąż masz miejsce na dysku.
tripleee
-2

Trochę bezpieczniejsza wersja niż przy użyciu xargs, również nie rekurencyjna: ls -p | grep -v '/$' | grep '\.pdf$' | while read file; do rm "$file"; done

Filtrowanie naszych katalogów tutaj jest trochę niepotrzebne, ponieważ „rm” i tak go nie usunie, i można je usunąć dla uproszczenia, ale po co uruchamiać coś, co na pewno zwróci błąd?

Kaplan Ilya
źródło
3
Nie jest to wcale bezpieczne i nie działa z nazwami plików z nowymi liniami, aby wskazać jeden oczywisty przypadek narożny. Parsowaniels jest częstym antywzorzec projektowy, który zdecydowanie należy unikać, i dodaje kilka dodatkowych błędów tutaj. To grep | greppo prostu niezbyt elegancki.
tripleee
W każdym razie nie jest tak, że jest to nowy i egzotyczny problem, który wymaga złożonego rozwiązania. Odpowiedzi findsą dobre i dobrze udokumentowane tutaj i gdzie indziej. Zobacz np. Mywiki.wooledge.org, aby uzyskać więcej informacji na ten temat i pokrewne tematy.
tripleee
-2

Używanie GNU równoległego (sudo apt install parallel ) jest bardzo łatwe

Uruchamia polecenia wielowątkowe, gdzie argumentem jest „{}”

Na przykład

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

Jonathan
źródło
Nie wiem, ale zgaduję, że dzieje się tak, ponieważ przekazywanie danych wyjściowych lsbezpośrednio do innych poleceń jest niebezpiecznym antypatternem - i fakt, że rozwinięcie symbolu wieloznacznego spowoduje taką samą awarię podczas wykonywania, lsjak w przypadku oryginalnego rmpolecenia .
Toby Speight,
Aby uzyskać kontekst na ten temat, zobacz ParsingLs . I parallelsprawia, że ​​niektórzy ludzie, którzy wolą unikać złożoności, są niewygodni - jeśli spojrzysz pod maską, jest to dość nieprzejrzyste. Zobacz wątek listy mailingowej na lists.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html między Stephane (jednym z greybeardów Unix i Linux StackExchange ) a Ole Tange (autor Parallel). xargs -Prównież działa równolegle, ale robi to w prostszy, głupszy sposób z mniejszą liczbą ruchomych części, dzięki czemu jego zachowanie jest znacznie łatwiejsze do przewidzenia i uzasadnienia.
Charles Duffy
-2

Aby usunąć pierwsze 100 plików:

rm -rf 'ls | głowa -100 '

Nikunj Ranpura
źródło
2
Niebezpieczne (lub byłoby, gdyby użyłeś cudzysłowów zgodnie z oczywistymi zamierzeniami) - jeśli jakakolwiek nazwa pliku zawiera metaznaki powłoki, w tym spacje, wyniki nie będą zgodne z zamierzeniami.
Toby Speight,
-5

Poniższa opcja wydaje się prosta dla tego problemu. Mam te informacje z innego wątku, ale pomogło mi to.

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

Wystarczy uruchomić powyższe polecenie, a wykona zadanie.

Amittal
źródło