Daftar argumen kesalahan terlalu lama untuk perintah rm, cp, mv

629

Saya memiliki beberapa ratus PDF di bawah direktori di UNIX. Nama-nama PDF sangat panjang (sekitar 60 karakter).

Ketika saya mencoba menghapus semua PDF bersama-sama menggunakan perintah berikut:

rm -f *.pdf

Saya mendapatkan kesalahan berikut:

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

Apa solusi untuk kesalahan ini? Apakah kesalahan ini terjadi untuk mvdan juga cpperintah? Jika ya, bagaimana cara menyelesaikan perintah ini?

Vicky
sumber
21
Anda mungkin menemukan tautan ini bermanfaat
another.anon.coward
1
Juga ini bisa relevan http://mywiki.wooledge.org/BashFAQ/095
Lorenzo Belli
4
@jww: Dan saya terus berpikir selama bertahun-tahun bahwa bash termasuk dalam "alat perangkat lunak yang biasa digunakan oleh pemrogram" - kategori yang pertanyaannya dapat ditanyakan di sini!
Vicky
@Nik - Menambahkan "... dalam skrip" tidak menarik. Ketika masalah dikurangi menjadi contoh Minimal, Lengkap, dan dapat diverifikasi , itu hanya pertanyaan tentang cara menjalankan perintah. Saya minta maaf jika saya kehilangan sesuatu yang jelas.
jww

Jawaban:

876

Alasan ini terjadi adalah karena bash sebenarnya memperluas tanda bintang ke setiap file yang cocok, menghasilkan baris perintah yang sangat panjang.

Coba ini:

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

Peringatan: ini adalah pencarian rekursif dan akan menemukan (dan menghapus) file di subdirektori juga. Tack on-f ke perintah rm hanya jika Anda yakin tidak ingin konfirmasi.

Anda dapat melakukan hal berikut untuk membuat perintah tidak rekursif:

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

Pilihan lain adalah menggunakan -deleteflag find :

find . -name "*.pdf" -delete
DPlusV
sumber
7
Tidak, xargssecara khusus membagi daftar dan mengeluarkan beberapa perintah jika perlu.
tripleee
7
@ Dennis: -maxdepth 1perlu argumen pertama setelah jalan.
Barton Chittenden
54
Find memiliki -deleteflag untuk menghapus file yang ditemukannya, dan bahkan jika tidak, itu masih dianggap praktik yang lebih baik untuk digunakan -execuntuk mengeksekusi rm, daripada memanggil xargs (yang sekarang 3 proses dan pipa bukannya proses tunggal dengan -deleteatau 2 proses dengan -exec).
scragar
3
@ ÉdouardLopez ... Tapi ini sedang membaca input yang dibatasi-NULL. Dan keseluruhannya dangerous (broken, exploitable, etc.), cukup konyol. Tidak diragukan lagi Anda harus berhati-hati saat menggunakan xargs, tetapi itu tidak cukup eval/evil.
Pasang kembali Monica,
4
@scragar Dengan -execmemanggil rm, jumlah proses akan menjadi 1 + jumlah file, meskipun jumlah proses bersamaan dari ini mungkin 2 (mungkin menemukan akan menjalankan proses rm secara bersamaan). Jumlah proses menggunakan xargsakan dikurangi secara dramatis menjadi 2 + n, di mana n adalah beberapa proses nomor kurang dari jumlah file (katakanlah jumlah file / 10, meskipun kemungkinan lebih tergantung pada panjang jalur). Dengan asumsi find melakukan penghapusan secara langsung, menggunakan -deleteharus menjadi satu-satunya proses yang akan dipanggil.
neuralmer
397

tl; dr

Ini adalah batasan kernel pada ukuran argumen baris perintah. Gunakan forloop sebagai gantinya.

Asal masalah

Ini adalah masalah sistem, terkait dengan execvedan ARG_MAXkonstan. Ada banyak dokumentasi tentang itu (lihat man execve , wiki debian ).

Pada dasarnya, ekspansi menghasilkan perintah (dengan parameternya) yang melebihi ARG_MAXbatas. Pada kernel 2.6.23, batasnya ditetapkan pada 128 kB. Konstanta ini telah ditingkatkan dan Anda bisa mendapatkan nilainya dengan mengeksekusi:

getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic

Solusi: Menggunakan forLoop

Gunakan forloop seperti yang disarankan pada BashFAQ / 095 dan tidak ada batasan kecuali untuk ruang RAM / memori:

Dry run untuk memastikan itu akan menghapus apa yang Anda harapkan:

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

Dan jalankan:

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

Ini juga merupakan pendekatan portabel karena glob memiliki perilaku yang kuat dan konsisten di antara shell ( bagian dari POSIX spec ).

Catatan: Sebagaimana dicatat oleh beberapa komentar, ini memang lebih lambat tetapi lebih dapat dipelihara karena dapat mengadaptasi skenario yang lebih kompleks, misalnya di mana seseorang ingin melakukan lebih dari satu tindakan.

Solusi: Menggunakan find

Jika Anda bersikeras, Anda dapat menggunakan findtetapi benar - benar tidak menggunakan xargs karena "berbahaya (rusak, dapat dieksploitasi, dll.) Saat membaca input yang tidak dibatasi NUL" :

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

Menggunakan -maxdepth 1 ... -deletealih-alih -exec rm {} +memungkinkan finduntuk hanya menjalankan pemanggilan sistem yang diperlukan sendiri tanpa menggunakan proses eksternal, karenanya lebih cepat (terima kasih atas komentar @chepner ).

Referensi

Édouard Lopez
sumber
31
Jawaban yang bagus, beginilah semua pertanyaan SO harus dijawab. Terima kasih!
tommed
1
+1 untuk menyebutkan forloop. Saya pernah menggunakan findsebelumnya, tapi saya selalu mencari cara melakukannya karena saya lupa pilihan, dll. Sepanjang waktu. fortampaknya lebih mudah untuk mengingat IMHO
Robert Dundon
3
Menggunakannya sebagai for f in *; do rm "$f"; donepesona
abdul qayyum
3
The find -execsolusi tampaknya JAUH lebih cepat dari forlingkaran.
threeve
2
Lima tahun kemudian pada 4.15.0 ( 4.15.0-1019-gcptepatnya) dan batasnya masih pada 2097152. Cukup menarik, mencari ARG_MAX di repo git linux memberikan hasil yang menunjukkan ARG_MAX berada di 131702.
Matt M.
181

findmemiliki -deletetindakan:

find . -maxdepth 1 -name '*.pdf' -delete
Pencuri
sumber
4
Ini masih akan mengembalikan "Daftar argumen terlalu lama". Setidaknya bagi saya itu. Menggunakan xargs, sesuai jawaban Dennis, berfungsi sebagaimana dimaksud.
Sergio
7
Kedengarannya seperti bug yang ditemukan.
ThiefMaster
3
@Sergio memiliki masalah yang sama, itu disebabkan oleh kutipan yang hilang di sekitar pola nama.
Luxian
argh, mengapa alat untuk mencari barang bahkan memiliki saklar untuk menghapus? apakah hanya aku yang merasa tidak perlu untuk mengatakan paling tidak dan juga berbahaya.
mathreadler
2
@ mathreadler Ini membahas fakta bahwa kasus penggunaan umum -execadalah untuk menghapus banyak file. -exec rm {} +akan melakukan hal yang sama, tetapi masih membutuhkan memulai setidaknya satu proses eksternal. -deletememungkinkan finduntuk hanya menjalankan pemanggilan sistem yang diperlukan itu sendiri tanpa menggunakan pembungkus eksternal.
chepner
21

Jawaban lain adalah memaksa xargsuntuk memproses perintah dalam batch. Misalnya ke deletefile 100sekaligus, cdmasuk ke direktori dan jalankan ini:

echo *.pdf | xargs -n 100 rm

portforwardpodcast
sumber
4
Untuk menghapus perintah di linux, yang bisa menjadi bencana jika Anda seorang insinyur dan Anda mengetik kesalahan, saya percaya itu adalah 'paling aman dan saya tahu apa yang terjadi' adalah yang terbaik. Bukan hal-hal mewah yang jika Anda lewatkan ketik titik akan membiarkan perusahaan Anda hancur dalam satu menit.
Kecerdasan Artifisial
1
Bagaimana kita bisa menjadikan ini ekspansi standar untuk perintah tertentu? Ada banyak perintah linux "standar" yang bagus di mana diketahui jika mereka membutuhkan semuanya sekaligus atau tidak (seperti "rm")
user1212212
1
Perhatikan bahwa ini hanya berfungsi jika echoshell dibangun. Jika Anda akhirnya menggunakan perintah echo, Anda masih akan berlari ke batas argumen program.
Toby Speight
14

Atau Anda dapat mencoba:

find . -name '*.pdf' -exec rm -f {} \;
Jon Lin
sumber
Ini juga menghapus file dari subdirektori. Bagaimana cara mencegahnya?
Vicky
@NikunjChauhan Tambahkan opsi -maxdepth:find . -maxdepth 1 -name '*.pdf' -exec rm -f {} \;
Jon Lin
Saya tidak dapat memasukkan opsi maxdepth
Vicky
Opsi itu mungkin merupakan opsi khusus Linux, sesuai jawaban @ Dennis, di atas (jawaban yang dipilih).
jvriesem
12

Jika Anda mencoba menghapus sejumlah besar file sekaligus (saya menghapus direktori dengan 485.000+ hari ini), Anda mungkin akan mengalami kesalahan ini:

/bin/rm: Argument list too long.

Masalahnya adalah ketika Anda mengetik sesuatu seperti rm -rf *, *diganti dengan daftar setiap file yang cocok, seperti "rm -rf file1 file2 file3 file4" dan seterusnya. Ada buffer memori yang relatif kecil yang dialokasikan untuk menyimpan daftar argumen ini dan jika diisi, shell tidak akan menjalankan program.

Untuk mengatasi masalah ini, banyak orang akan menggunakan perintah find untuk menemukan setiap file dan meneruskannya satu per satu ke perintah "rm" seperti ini:

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

Masalah saya adalah saya harus menghapus 500.000 file dan itu terlalu lama.

Saya menemukan cara yang jauh lebih cepat untuk menghapus file - perintah "find" memiliki bendera "-delete" yang ada di dalamnya! Inilah yang akhirnya saya gunakan:

find . -type f -delete

Dengan menggunakan metode ini, saya menghapus file dengan kecepatan sekitar 2000 file / detik - jauh lebih cepat!

Anda juga dapat menampilkan nama file saat Anda menghapusnya:

find . -type f -print -delete

... atau bahkan menunjukkan berapa banyak file yang akan dihapus, lalu berapa lama waktu yang dibutuhkan untuk menghapusnya:

root@devel# ls -1 | wc -l && time find . -type f -delete
100000
real    0m3.660s
user    0m0.036s
sys     0m0.552s
Bibin Joseph
sumber
Terima kasih. Saya lakukan sudo find . -type f -deleteuntuk menghapus sekitar 485 ribu file dan itu berhasil untuk saya. Butuh waktu sekitar 20 detik.
Nigel Alderton
11

Anda dapat mencoba ini:

for f in *.pdf
do
  rm $f
done

EDIT: Komentar ThiefMaster menyarankan saya untuk tidak mengungkapkan praktik berbahaya seperti itu kepada jedis shell muda, jadi saya akan menambahkan versi yang lebih "lebih aman" (demi menjaga hal-hal ketika seseorang memiliki file "-rf. ... pdf")

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

Setelah menjalankan hal di atas, cukup buka file /tmp/dummy.sh di fav Anda. edit dan periksa setiap baris untuk nama file berbahaya, beri komentar jika ditemukan.

Kemudian salin skrip dummy.sh di direktori kerja Anda dan jalankan.

Semua ini untuk alasan keamanan.

BigMike
sumber
5
Saya pikir ini akan melakukan hal-hal yang sangat baik dengan file bernama eg-rf .. .pdf
ThiefMaster
ya itu akan, tetapi umumnya ketika digunakan di shell, penerbit perintah "harus" melihat apa yang dia lakukan :). Sebenarnya saya lebih suka untuk mengarahkan ulang ke file dan kemudian memeriksa setiap baris.
BigMike
2
Ini tidak mengutip "$ f". Itulah yang dibicarakan oleh ThiefMaster. -rflebih diutamakan -i, sehingga versi 2 Anda tidak lebih baik (tanpa inspeksi manual). Dan pada dasarnya tidak berguna untuk penghapusan massal, karena meminta setiap file.
Peter Cordes
7

Anda bisa menggunakan array bash:

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

Dengan cara ini akan dihapus dalam batch 1000 file per langkah.

danjperron
sumber
2
Untuk sejumlah besar file ini sepertinya jauh lebih cepat
James Tocknell
5

Anda dapat menggunakan pujian ini

find -name "*.pdf"  -delete
Sarath Ak
sumber
4

The rm perintah memiliki keterbatasan file yang dapat Anda menghapus simultan.

Satu kemungkinan Anda dapat menghapusnya menggunakan beberapa kali perintah rm berdasarkan pola file Anda, seperti:

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

Anda juga dapat menghapusnya melalui perintah find :

find . -name "*.pdf" -exec rm {} \;
Fabio Farath
sumber
3
Tidak, rmtidak memiliki batasan jumlah file yang akan diproses (selain itu argctidak boleh lebih besar dari INT_MAX). Ini keterbatasan kernel pada ukuran maksimum dari seluruh argumen array (itu sebabnya panjang nama file signifikan).
Toby Speight
3

Jika mereka adalah nama file dengan spasi atau karakter khusus, gunakan:

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

Kalimat ini mencari semua file di direktori saat ini (-maxdepth 1) dengan ekstensi pdf (-name '* .pdf'), dan kemudian hapus masing-masing (-exec rm "{}").

Ekspresi {} ganti nama file, dan, {{} "tetapkan nama file sebagai string, termasuk spasi atau karakter khusus.

Alejandro Salamanca Mazuelo
sumber
Sementara potongan kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan tentang bagaimana dan mengapa ini menyelesaikan masalah akan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, bukan hanya orang yang bertanya sekarang! Harap edit jawaban Anda untuk menambahkan penjelasan, dan berikan indikasi batasan dan asumsi apa yang berlaku.
Toby Speight
Intinya -execadalah bahwa Anda tidak meminta shell. Kutipan di sini sama sekali tidak berguna. (Mereka mencegah ekspansi wildcard dan pemisahan token pada string di shell tempat Anda mengetik perintah ini, tetapi string {}tidak mengandung spasi atau karakter wildcard shell.)
tripleee
2

saya menghadapi masalah yang sama saat menyalin direktori sumber formulir ke tujuan

direktori sumber memiliki file ~ 3 lakc

saya menggunakan cp dengan opsi -r dan itu berhasil untuk saya

cp -r abc / def /

itu akan menyalin semua file dari abc ke def tanpa memberi peringatan daftar Argument terlalu lama

pengguna3405020
sumber
Saya tidak tahu mengapa seseorang menurunkan ini, bahkan tanpa mengomentari itu (itu kebijakan, teman-teman!). Saya perlu menghapus semua file di dalam folder (pertanyaannya tidak khusus tentang PDF, ingatlah), dan untuk itu, trik ini bekerja dengan baik, yang harus dilakukan pada akhirnya adalah membuat ulang folder yang terhapus ketika Saya menggunakan `rm -R / path / ke / folder".
Thomas Tempelmann
1
Ini bekerja karena dalam kasus OP, ia menggunakan *, yang diperluas ke daftar .pdf, memberikan direktori akan menyebabkan ini diperlakukan secara internal, sehingga, tidak harus berurusan dengan masalah OP. Saya pikir itu diturunkan karena alasan itu. Mungkin tidak dapat digunakan untuk OP jika ia memiliki direktori bersarang atau file lain (bukan pdf) di direktori-nya
Alvein
2

Coba ini juga Jika Anda ingin menghapus di atas 30/90 hari (+) atau yang lain di bawah 30/90 (-) hari file / folder maka Anda dapat menggunakan perintah ex di bawah ini

Mis: Selama 90 hari tidak termasuk di atas setelah 90 hari menghapus file / folder, itu berarti 91,92 .... 100 hari

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

Mis: Hanya file 30 hari terbaru yang ingin Anda hapus kemudian gunakan perintah di bawah ini (-)

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

Jika Anda ingin giz file selama lebih dari 2 hari file

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

Jika Anda ingin melihat file / folder hanya dari satu bulan terakhir. Ex:

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

Di atas 30 hari lagi hanya daftar file / folder Mis:

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

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

Saya terkejut tidak ada ulimitjawaban di sini. Setiap kali saya memiliki masalah ini, saya berakhir di sini atau di sini . Saya mengerti solusi ini memiliki keterbatasan tetapi ulimit -s 65536sepertinya sering melakukan trik untuk saya.

dps
sumber
1

Saya memiliki masalah yang sama dengan folder yang penuh dengan gambar sementara yang tumbuh hari demi hari dan perintah ini membantu saya menghapus folder

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

Perbedaannya dengan perintah lain adalah parameter mtime yang hanya akan mengambil file yang lebih lama dari X hari (dalam contoh 50 hari)

Menggunakan itu berkali-kali, berkurang pada setiap eksekusi dalam rentang hari, saya dapat menghapus semua file yang tidak perlu

Brugolo
sumber
1

Saya hanya tahu cara mengatasinya. Idenya adalah untuk mengekspor daftar file pdf yang Anda miliki ke file. Kemudian bagi file itu menjadi beberapa bagian. Kemudian hapus file pdf yang tercantum di setiap bagian.

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

wc -l adalah untuk menghitung berapa banyak baris yang ada di list.txt. Ketika Anda memiliki gagasan tentang berapa lama, Anda dapat memutuskan untuk membaginya menjadi dua, empat atau seterusnya. Menggunakan perintah split -l Misalnya, pisahkan masing-masing dalam 600 baris.

split -l 600 list.txt

ini akan membuat beberapa file bernama xaa, xab, xac dan sebagainya tergantung pada bagaimana Anda membaginya. Sekarang untuk "mengimpor" setiap daftar dalam file tersebut ke dalam perintah rm, gunakan ini:

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

Maaf untuk bahasa Inggris saya yang buruk.

thai_phan
sumber
5
Jika Anda memiliki file dengan nama pdf_format_sucks.docxini, ini akan dihapus juga ... ;-) Anda harus menggunakan ekspresi reguler yang tepat dan akurat ketika menerima file pdf.
FooF
1
Lebih baik, tetapi still_pdf_format_sucks.docxakan dihapus. Titik .dalam ".pdf"ekspresi reguler cocok dengan karakter apa pun. Saya akan menyarankan "[.]pdf$"bukan .pdf.
FooF
1

Saya mengalami masalah ini beberapa kali. Banyak solusi akan menjalankan rmperintah untuk setiap file yang perlu dihapus. Ini sangat tidak efisien:

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

Saya akhirnya menulis skrip python untuk menghapus file berdasarkan 4 karakter pertama dalam nama file:

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

Ini bekerja sangat baik untuk saya. Saya dapat menghapus lebih dari 2 juta file temp dalam folder dalam waktu sekitar 15 menit. Saya berkomentar tar keluar dari sedikit kode sehingga siapa pun dengan sedikit atau tanpa pengetahuan python dapat memanipulasi kode ini.

Pedro Montero
sumber
1

Dan satu lagi:

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

printfadalah shell builtin, dan sejauh yang saya tahu selalu seperti itu. Sekarang mengingat bahwa printfitu bukan perintah shell (tapi builtin), itu tidak tunduk pada "argument list too long ... " kesalahan fatal.

Jadi kita dapat menggunakannya dengan aman dengan pola-pola shell globbing seperti *.[Pp][Dd][Ff], kemudian kita mem-pipe outputnya untuk menghapus ( rm) perintah, melalui xargs, yang memastikan itu cukup cocok dengan nama file di baris perintah agar tidak gagal rmperintah, yang merupakan shell perintah.

The \0dalam printfMelayani sebagai pemisah null untuk nama file Wich kemudian diproses oleh xargsperintah, menggunakannya ( -0) sebagai pemisah, sehingga rmtidak gagal ketika ada spasi putih atau karakter khusus lainnya dalam nama file.

lind
sumber
1
Sementara potongan kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan tentang bagaimana dan mengapa ini menyelesaikan masalah akan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, bukan hanya orang yang bertanya sekarang! Harap edit jawaban Anda untuk menambahkan penjelasan, dan berikan indikasi batasan dan asumsi apa yang berlaku.
Toby Speight
Khususnya, jika printfshell tidak dibangun, itu akan dikenakan batasan yang sama.
Toby Speight
0

Anda dapat membuat folder temp, memindahkan semua file dan sub-folder yang ingin Anda simpan ke folder temp lalu menghapus folder lama dan mengganti nama folder temp ke folder lama coba contoh ini sampai Anda yakin untuk melakukannya langsung:

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

yang rm -r big_folderakan menghapus semua file dalam big_foldertidak peduli berapa banyak. Anda hanya harus sangat berhati-hati terlebih dahulu untuk memiliki semua file / folder yang ingin Anda simpan, dalam hal inifile1.pdf

Keithhn
sumber
0

Untuk menghapus semua *.pdfdalam direktori/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/

Untuk menghapus file tertentu melalui rsyncmenggunakan wildcard mungkin merupakan solusi tercepat jika Anda memiliki jutaan file. Dan itu akan mengatasi kesalahan yang Anda dapatkan.


(Langkah Opsional): KERING KERING. Untuk memeriksa apa yang akan dihapus tanpa menghapus. `

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

. . .

Klik tips dan trik rsync untuk hacks rsync lainnya

Raman Kathpalia
sumber
0

Saya menemukan bahwa untuk daftar file yang sangat besar (> 1e6), jawaban ini terlalu lambat. Berikut adalah solusi menggunakan pemrosesan paralel dalam python. Saya tahu, saya tahu, ini bukan linux ... tapi tidak ada yang bekerja di sini.

(Ini menghemat waktu saya)

# 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
sumber
0

Saya telah menghadapi masalah yang sama ketika ada jutaan file log tidak berguna yang dibuat oleh aplikasi yang mengisi semua inode. Saya terpaksa "mencari", mendapatkan semua file "terletak" d ke file teks dan kemudian menghapusnya satu per satu. Butuh waktu tetapi melakukan pekerjaan!

asatsi
sumber
Ini cukup kabur dan mengharuskan Anda untuk menginstal locatekembali ketika Anda masih memiliki ruang pada disk Anda.
tripleee
-2

Versi yang sedikit lebih aman daripada menggunakan xargs, juga tidak rekursif: ls -p | grep -v '/$' | grep '\.pdf$' | while read file; do rm "$file"; done

Memfilter direktori kami di sini sedikit tidak perlu karena 'rm' tidak akan menghapusnya, dan itu dapat dihapus untuk kesederhanaan, tetapi mengapa menjalankan sesuatu yang pasti akan mengembalikan kesalahan?

Kaplan Ilya
sumber
3
Ini tidak aman sama sekali, dan tidak bekerja dengan nama file dengan baris baru di dalamnya, untuk menunjukkan satu kasus sudut yang jelas. Parsingls adalah antipattern umum yang harus dihindari, dan menambahkan sejumlah bug tambahan di sini. Hanya grep | grepsaja tidak terlalu elegan.
tripleee
Bagaimanapun, ini bukan masalah baru dan eksotis yang membutuhkan solusi yang kompleks. Jawabannya findbagus, dan didokumentasikan dengan baik di sini dan di tempat lain. Lihat misalnya mywiki.wooledge.org untuk informasi lebih lanjut tentang ini dan topik terkait.
tripleee
-2

Menggunakan GNU parallel ( sudo apt install parallel) sangat mudah

Itu menjalankan perintah multithreaded di mana '{}' adalah argumen yang dilewati

Misalnya

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

Jonathan
sumber
Saya tidak tahu, tapi saya rasa itu karena mengirimkan output lslangsung ke perintah lain adalah antipattern yang berbahaya - itu, dan fakta bahwa ekspansi wildcard akan menyebabkan kegagalan yang sama ketika mengeksekusi lsseperti yang dialami seperti yang dialami pada rmperintah asli .
Toby Speight
Untuk konteksnya, lihat ParsingLs . Dan parallelmembuat beberapa orang yang lebih suka menghindari kerumitan tidak nyaman - jika Anda melihat di bawah tenda, itu cukup buram. Lihat utas milis di lists.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html antara Stephane (salah satu dari Unix & Linux StackExchange greybeards) dan Ole Tange (penulis paralel). xargs -Pjuga lumpuh, tetapi melakukannya dengan cara yang lebih sederhana dan bodoh dengan bagian bergerak yang lebih sedikit, membuat perilakunya jauh lebih mudah untuk diprediksi dan dipikirkan.
Charles Duffy
-2

Untuk menghapus 100 file pertama:

rm -rf 'ls | kepala -100 '

Nikunj Ranpura
sumber
2
Berbahaya (atau itu akan terjadi jika Anda menggunakan backquotes seperti yang dimaksudkan) - jika ada nama file yang mengandung karakter meta shell, termasuk spasi, maka hasilnya tidak akan seperti yang Anda inginkan.
Toby Speight
-5

Opsi di bawah ini tampaknya sederhana untuk masalah ini. Saya mendapat info ini dari utas lain tetapi itu membantu saya.

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

Jalankan saja satu perintah di atas dan itu akan melakukan tugas.

Amittal
sumber