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?


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

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


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

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


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 {} \;

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

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.


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.


2
W przypadku dużej liczby plików wydaje się to znacznie szybsze
— James Tocknell


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 {} \;

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.


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


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 {} \;

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.


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


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.


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.


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.


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


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


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)

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ę!


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?


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 {}'


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 '


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.