आरएम, सीपीपी, एमवी कमांड के लिए तर्क सूची बहुत लंबी है


629

मेरे पास UNIX में एक निर्देशिका के तहत कई सौ PDF हैं। PDFs के नाम वास्तव में लंबे (लगभग 60 वर्ण) हैं।

जब मैं निम्नलिखित आदेश का उपयोग करके सभी PDF को एक साथ हटाने का प्रयास करता हूं:

rm -f *.pdf

मुझे निम्नलिखित त्रुटि मिलती है:

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

इस त्रुटि का समाधान क्या है? क्या यह त्रुटि mvऔर cpआदेशों के लिए भी है? यदि हाँ, तो इन कमांडों को कैसे हल करें?


21
आपको यह लिंक उपयोगी लग सकता है
.anon.coward 7


1
इसके अलावा यह प्रासंगिक हो सकता है http://mywiki.wooledge.org/BashFAQ/095
लोरेंजो बेली

4
@jww: और मैंने इतने सालों तक यह सोचना जारी रखा कि "प्रोग्रामर्स द्वारा आमतौर पर उपयोग किए जाने वाले सॉफ़्टवेयर टूल्स" के तहत बैश होता है - एक ऐसी श्रेणी जिसके सवाल यहाँ पूछे जा सकते हैं!
विक्की

@ नाइक - जोड़ना "... एक स्क्रिप्ट में" सम्मोहक नहीं है। जब समस्या को कम से कम, पूर्ण और सत्यापन योग्य उदाहरण के लिए कम कर दिया जाता है , तो यह कमांड चलाने के तरीके पर एक सवाल है। मेरी माफी अगर मुझे कुछ स्पष्ट याद आ रही है।
jww

जवाबों:


876

ऐसा इसलिए होता है क्योंकि बैश वास्तव में हर मेल खाने वाली फ़ाइल में तारांकन चिह्न का विस्तार करता है, जो एक बहुत लंबी कमांड लाइन का निर्माण करता है।

इसे इस्तेमाल करे:

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

चेतावनी: यह एक पुनरावर्ती खोज है और उपनिर्देशिकाओं में भी (और हटाएं) फाइलों को ढूंढेगा। -fयदि आप सुनिश्चित हैं कि आप पुष्टि नहीं करना चाहते हैं, तो केवल rm कमांड पर टिक करें।

कमांड को गैर-पुनरावर्ती बनाने के लिए आप निम्न कार्य कर सकते हैं:

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

एक अन्य विकल्प खोज के -deleteझंडे का उपयोग करना है :

find . -name "*.pdf" -delete

7
नहीं, xargsविशेष रूप से सूची को विभाजित करता है और यदि आवश्यक हो तो कई आदेश जारी करता है।
ट्रिपल जूल

7
@ डेनिस: -maxdepth 1पथ के बाद पहला तर्क होना चाहिए।
बार्टन चित्तेंडेन

54
-deleteफाइल्स में पाई जाने वाली फाइलों को हटाने के लिए एक ध्वज होता है, और भले ही यह नहीं था कि इसे अभी भी -execएक्सएमआर को लागू करने के बजाय आरएम को निष्पादित करने के लिए उपयोग करने के लिए बेहतर अभ्यास माना जाएगा (जो अब 3 प्रक्रियाएं हैं और एक एकल प्रक्रिया के बजाय एक पाइप है। -deleteया 2 प्रक्रियाओं के साथ -exec)।
स्कगर

3
@ IsdouardLopez ... लेकिन यह NULL- सीमांकित इनपुट पढ़ रहा है। और पूरा dangerous (broken, exploitable, etc.), काफी हास्यास्पद है। निस्संदेह आपको उपयोग करते समय सावधान रहना चाहिए xargs, लेकिन यह काफी नहीं है eval/evil
मोनिका प्लीज

4
@ सागर -execकॉलिंग के साथ rm, प्रक्रियाओं की संख्या 1 + फाइलों की संख्या होगी, हालांकि इस से समवर्ती प्रक्रियाओं की संख्या 2 हो सकती है (शायद पता चलेगा कि rm प्रक्रियाओं को समवर्ती रूप से निष्पादित किया जाएगा)। उपयोग की जाने वाली प्रक्रियाओं की संख्या xargsनाटकीय रूप से 2 + n तक कम हो जाएगी, जहां n कुछ संख्या में फ़ाइलों की संख्या से कम प्रक्रियाएं हैं (फ़ाइलों की संख्या 10 (हालांकि पथों की लंबाई के आधार पर अधिक होने की संभावना है)। यह मानकर कि विलोपन सीधे होता है, का उपयोग -deleteकेवल एक ही प्रक्रिया होनी चाहिए जिसे लागू किया जाएगा।
न्यूरल जैमर

396

tl; डॉ

यह कमांड लाइन तर्क के आकार पर एक कर्नेल सीमा है। forइसके बजाय एक लूप का उपयोग करें ।

समस्या की उत्पत्ति

यह एक सिस्टम इशू है, इससे संबंधित है execveऔर ARG_MAXनिरंतर है। उस बारे में बहुत सारे दस्तावेज हैं (देखें आदमी को निष्पादित करें , डेबियन की विकी )।

मूल रूप से, विस्तार एक कमांड (इसके मापदंडों के साथ) का उत्पादन करता है जो ARG_MAXसीमा से अधिक है। कर्नेल पर 2.6.23, सीमा निर्धारित की गई थी 128 kB। यह स्थिरांक बढ़ा दिया गया है और आप निष्पादित करके इसका मूल्य प्राप्त कर सकते हैं:

getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic

समाधान: forलूप का उपयोग करना

BashFAQ / 095for पर अनुशंसित एक लूप का उपयोग करें और रैम / मेमोरी स्पेस को छोड़कर कोई सीमा नहीं है:

यह पता लगाने के लिए सूखा चलाएं कि आप क्या उम्मीद करेंगे:

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

और इसे निष्पादित करें:

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

इसके अलावा यह एक पोर्टेबल दृष्टिकोण है क्योंकि गोला का गोले के बीच मजबूत और निरंतर व्यवहार होता है ( पोसिक्स कल्पना का हिस्सा )।

नोट: जैसा कि कई टिप्पणियों से पता चला है, यह वास्तव में धीमा है, लेकिन अधिक बनाए रखने योग्य है क्योंकि यह अधिक जटिल परिदृश्यों को अनुकूलित कर सकता है, जैसे कि जहां एक से अधिक कार्रवाई करना चाहते हैं।

समाधान: का उपयोग करना find

यदि आप जोर देते हैं, तो आप उपयोग कर सकते हैं findलेकिन वास्तव में xargs का उपयोग न करें क्योंकि यह गैर-एनयूएल-सीमांकित इनपुट को पढ़ने पर खतरनाक (टूटा हुआ, शोषक, आदि) है : "

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

-maxdepth 1 ... -deleteइसके बजाय का उपयोग करने की -exec rm {} +अनुमति देता findहै बस आवश्यक प्रक्रिया को निष्पादित करने के लिए एक बाहरी प्रक्रिया का उपयोग किए बिना खुद को कॉल करता है, इसलिए तेजी से ( @chepner टिप्पणी के लिए धन्यवाद )।

संदर्भ


31
महान जवाब, यह है कि सभी SO प्रश्नों का उत्तर कैसे दिया जाना चाहिए। धन्यवाद!
tommed

1
forलूप का उल्लेख करने के लिए +1 । मैंने पहले भी इस्तेमाल किया है find, लेकिन मैं हमेशा देख रहा हूं कि मैं इसे कैसे करूं क्योंकि मैं हर समय विकल्पों को भूल जाता हूं। for
रॉबर्ट डंडन

3
इसे for f in *; do rm "$f"; doneएक आकर्षण के रूप में काम करते थे
पेट क्यूयूम

3
find -execसमाधान बहुत तेजी से हो रहा है forपाश।
तीन

2
पांच साल बाद 4.15.0 में ( 4.15.0-1019-gcpसटीक होना करने के लिए) और सीमा दिलचस्प बात यह 2097152. पर अब भी है linux Git रेपो पर ARG_MAX के लिए खोज दिखा एक परिणाम देता है ARG_MAX 131702. पर होना
मैट एम

181

findएक -deleteकार्रवाई की है:

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

4
यह अभी भी "तर्क सूची बहुत लंबा है" लौटाएगा। कम से कम मेरे लिए यह करता है। xargsडेनिस के जवाब के अनुसार, उपयोग करना , इरादा के अनुसार काम करता है।
सर्जियो

7
जो खोजने में एक बग की तरह लगता है।
ThiefMaster

3
@ शेरगियो के पास एक ही मुद्दा था, यह नाम पैटर्न के आसपास लापता उद्धरणों के कारण था।
लक्सियन

argh, सामान खोजने के लिए एक उपकरण भी हटाने के लिए एक स्विच क्यों है? क्या यह वास्तव में सिर्फ मेरे लिए है जो इसे कम से कम और खतरनाक भी कहना अनावश्यक है।
मैथ्रेडलर

2
@ मैथ्रेडलर यह इस तथ्य को संबोधित करता है कि -execफाइलों का एक गुच्छा हटाने के लिए एक सामान्य उपयोग मामला है। -exec rm {} +एक ही काम करेगा, लेकिन अभी भी कम से कम एक बाहरी प्रक्रिया शुरू करने की आवश्यकता है। बस आवश्यक सिस्टम को निष्पादित करने की -deleteअनुमति देता findहै एक बाहरी आवरण का उपयोग किए बिना।
चेपनर

21

एक अन्य उत्तर xargsबैचों में आदेशों को संसाधित करने के लिए बाध्य करना है। उदाहरण के लिए , निर्देशिका में deleteफ़ाइलों 100को एक बार cdमें और इसे चलाने के लिए:

echo *.pdf | xargs -n 100 rm


4
लिनक्स में कमांड डिलीट करने के लिए, जो कि एक आपदा हो सकती है यदि आप एक इंजीनियर हैं और आपने एक गलती टाइप की है, मेरा मानना ​​है कि यह 'सबसे सुरक्षित है और मुझे पता है कि क्या चल रहा है' सबसे अच्छा है। नहीं फैंसी सामान है कि यदि आप एक प्रकार की याद आती है, तो आपकी कंपनी एक मिनट में दुर्घटनाग्रस्त हो जाएगी।
आर्टिफिशियललीन्जेंस

1
हम इसे कुछ आदेशों के लिए डिफ़ॉल्ट विस्तार कैसे बना सकते हैं? वहाँ एक अच्छा कई "मानक" लिनक्स कमांड्स हैं, जहां यह ज्ञात है कि उन्हें एक बार में सभी की आवश्यकता है या नहीं (जैसे "आरएम")
user1212212

1
ध्यान दें कि यह केवल वहीं काम करता है जहां echoशेल बिलिन है। यदि आप कमांड का उपयोग कर रहे हैं echo, तो आप अभी भी प्रोग्राम तर्क सीमा में चलेंगे।
टोबी स्पाईट

14

या आप कोशिश कर सकते हैं:

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

यह उपनिर्देशिकाओं से फ़ाइलों को भी हटा देता है। इसे कैसे रोका जाए?
विक्की

@NikunjChauhan Add -maxdepth विकल्प:find . -maxdepth 1 -name '*.pdf' -exec rm -f {} \;
जॉन लिन

मैं
विकी

वह विकल्प @-डेनिस के उत्तर, ऊपर (चयनित उत्तर) के अनुसार, लिनक्स-ओनली विकल्प हो सकता है।
jvriesem

12

यदि आप एक समय में बहुत बड़ी संख्या में फ़ाइलों को हटाने की कोशिश कर रहे हैं (मैंने 485,000+ आज के साथ एक निर्देशिका को हटा दिया है), तो आप संभवतः इस त्रुटि में भाग लेंगे:

/bin/rm: Argument list too long.

समस्या यह है कि जब आप कुछ टाइप करते हैं rm -rf *, तो *उसे हर मेल खाते की सूची से बदल दिया जाता है, जैसे "rm -rf file1 file2 file3 file4" और इसी तरह। इस तर्क की सूची को संग्रहीत करने के लिए स्मृति का एक अपेक्षाकृत छोटा बफर आवंटित किया गया है और यदि इसे भरा जाता है, तो शेल प्रोग्राम को निष्पादित नहीं करेगा।

इस समस्या को हल करने के लिए, बहुत सारे लोग प्रत्येक फ़ाइल को खोजने के लिए खोज कमांड का उपयोग करेंगे और उन्हें इस तरह "rm" कमांड पर एक-एक करके पास करेंगे:

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

मेरी समस्या यह है कि मुझे 500,000 फ़ाइलों को हटाने की आवश्यकता थी और यह बहुत लंबा हो रहा था।

मैं फ़ाइलों को हटाने के एक बहुत तेज़ तरीके से ठोकर खाई - "खोज" कमांड में एक "-डेलीट" झंडा है जो सही में बनाया गया है! यहाँ मैंने क्या उपयोग किया है:

find . -type f -delete

इस पद्धति का उपयोग करते हुए, मैं लगभग 2000 फ़ाइलों / सेकंड की दर से फ़ाइलों को हटा रहा था - बहुत तेजी से!

आप फ़ाइलनाम भी दिखा सकते हैं जैसे आप उन्हें हटा रहे हैं:

find . -type f -print -delete

… या यह भी बताएं कि कितनी फाइलें हटाई जाएंगी, फिर उन्हें हटाने में कितना समय लगता है:

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

धन्यवाद। मैंने sudo find . -type f -deleteलगभग 485 हजार फाइलें डिलीट करने के लिए काम किया और इसने मेरे लिए काम किया। लगभग 20 सेकंड का समय लिया।
निगेल एल्डर्टन

11

आप यह कोशिश कर सकते हैं:

for f in *.pdf
do
  rm $f
done

संपादित करें: ThiefMaster टिप्पणी मुझे सुझाव देती है कि युवा शेल की जेडिस के लिए इस तरह के खतरनाक अभ्यास का खुलासा न करें, इसलिए मैं अधिक "सुरक्षित" संस्करण जोड़ूंगा (चीजों को संरक्षित करने के लिए जब किसी के पास "-rf ..pdf" फ़ाइल हो)।

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

उपरोक्त चलाने के बाद, बस अपने fav में /tmp/dummy.sh फ़ाइल खोलें। संपादक और खतरनाक फ़ाइल नाम के लिए हर एक लाइन की जाँच करें, अगर उन्हें पाया गया तो टिप्पणी करें।

फिर अपने वर्किंग डायर में डमी.श स्क्रिप्ट को कॉपी करें और चलाएं।

सुरक्षा कारणों से यह सब।


5
मुझे लगता है कि यह उदाहरण के लिए एक फ़ाइल के साथ वास्तव में अच्छी चीजें करेगा-rf .. .pdf
ThiefMaster

हाँ, यह होगा, लेकिन आम तौर पर जब शेल में उपयोग किया जाता है, तो कमांड के जारीकर्ता को "जो वह कर रहा है उस पर एक नज़र डालना चाहिए"। वास्तव में मैं एक फ़ाइल पर पुनर्निर्देशित करना पसंद करता हूं और फिर हर एक पंक्ति का निरीक्षण करता हूं।
बिगमीक

2
यह "$ f" का उद्धरण नहीं देता है। यही थिफ़मैस्टर की बात हो रही थी। -rfपूर्वता लेता है -i, इसलिए आपका दूसरा संस्करण बेहतर नहीं है (मैनुअल निरीक्षण के बिना)। और मूल रूप से हर फ़ाइल के लिए संकेत देने के कारण, बड़े पैमाने पर हटाने के लिए बेकार है।
पीटर कॉर्ड्स

7

आप एक बैश सरणी का उपयोग कर सकते हैं:

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

इस तरह यह प्रति चरण 1000 फ़ाइलों के बैचों में मिट जाएगा।


2
बड़ी संख्या में फ़ाइलों के लिए यह काफी तेज लगता है
जेम्स टॉक्नेल


4

Rm कमांड फ़ाइलें जो आप एक साथ निकाल सकते हैं की एक सीमा है।

एक संभावना है कि आप उन्हें अपने फ़ाइल पैटर्न पर कई बार rm कमांड बेस का उपयोग करके निकाल सकते हैं , जैसे:

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

तुम भी उन्हें खोजने के आदेश के माध्यम से निकाल सकते हैं :

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

3
नहीं, rmऐसी कोई सीमा नहीं होगी कि यह कितनी फ़ाइलों को संसाधित करेगा (इसके अलावा अन्य)argc बड़ी नहीं हो सकती है INT_MAX)। यह संपूर्ण तर्क सरणी के अधिकतम आकार पर कर्नेल की सीमा है (यही कारण है कि फ़ाइल नाम की लंबाई महत्वपूर्ण है)।
टोबे स्पाइट

3

यदि वे रिक्त स्थान या विशेष वर्णों के साथ फ़ाइल नाम रखते हैं, तो उपयोग करें:

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

यह वाक्य मौजूदा निर्देशिका (-maxdepth 1) में सभी फाइलों को एक्सटेंशन पीडीएफ (-name '* .pdf') के साथ खोजता है, और फिर, प्रत्येक को हटाता है (-exec rm "{}")।

एक्सप्रेशन {} फाइल के नाम को रिप्लेस करता है, और "{}" फाइलनाम को स्ट्रिंग के रूप में सेट करता है, जिसमें स्पेस या स्पेशल कैरेक्टर शामिल हैं।


हालांकि यह कोड स्निपेट प्रश्न को हल कर सकता है, जिसमें यह भी बताया गया है कि यह समस्या कैसे और क्यों हल करती है वास्तव में आपके पोस्ट की गुणवत्ता को बेहतर बनाने में मदद करेगी । याद रखें कि आप भविष्य में पाठकों के लिए सवाल का जवाब दे रहे हैं, न कि केवल उस व्यक्ति से जो अब पूछ रहा है! कृपया स्पष्टीकरण जोड़ने के लिए अपना उत्तर संपादित करें, और इस बात का संकेत दें कि क्या सीमाएँ और मान्यताएँ लागू होती हैं।
टोबी स्पाईट

इसका पूरा मतलब -execयह है कि आप एक शेल का इस्तेमाल नहीं करते हैं। यहाँ उद्धरण बिल्कुल उपयोगी नहीं है। (वे शेल में स्ट्रिंग पर किसी भी वाइल्डकार्ड विस्तार और टोकन विभाजन को रोकते हैं , जहां आप इस कमांड में टाइप करते हैं, लेकिन स्ट्रिंग {}में कोई
व्हाट्सएप

2

मुझे गंतव्य पर फ़ॉर्म स्रोत निर्देशिका की प्रतिलिपि बनाते समय एक ही समस्या का सामना करना पड़ रहा था

स्रोत निर्देशिका में फ़ाइल 3 ~ lakcs थी

मैं विकल्प के साथ सीपीआर -r का इस्तेमाल किया और यह मेरे लिए काम किया है

cp -r abc / def /

यह बहुत लंबे समय तक आर्ग्युमेंट लिस्ट की चेतावनी दिए बिना एबीसी से लेकर डीईएफ तक सभी फाइलों को कॉपी करेगा


मुझे नहीं पता कि किसी ने इस पर टिप्पणी क्यों की, उस पर भी टिप्पणी किए बिना (यह नीति, लोग!)। मुझे एक फ़ोल्डर के अंदर सभी फ़ाइलों को हटाने की आवश्यकता थी (प्रश्न विशेष रूप से पीडीएफ, आपके मन में) के बारे में नहीं है, और उसके लिए, यह चाल अच्छी तरह से काम कर रही है, सभी को अंत में उस फ़ोल्डर को फिर से बनाना होगा जो हटाए जाने के साथ मिला मैंने `rm -R / path / to / folder 'का उपयोग किया।
थॉमस टेम्प्लेमन

1
यह काम करता है क्योंकि ओपी के मामले में, वह * का उपयोग कर रहा था, जो कि .pdf की एक विशाल सूची में विस्तारित हो गया था, एक निर्देशिका देने से यह आंतरिक रूप से व्यवहार किया जाएगा, इस प्रकार, ओपी के मुद्दे से निपटने के लिए नहीं। मुझे लगता है कि यह उस कारण से अस्वीकृत हो गया था। यह ओपी के लिए उपयोग करने योग्य नहीं हो सकता है यदि उसकी निर्देशिका में नेस्टेड डायरेक्टरी या अन्य फाइलें (पीडीएफ नहीं) हैं
एल्विन

2

इसे भी आज़माएं यदि आप 30/90 दिन (+) से ऊपर हटाना चाहते हैं या 30/90 (-) दिनों की फ़ाइलों / फ़ोल्डरों से नीचे हैं तो आप नीचे दिए गए पूर्व आदेशों का उपयोग कर सकते हैं

Ex: 90 दिनों के लिए 90 दिनों की फ़ाइलों / फ़ोल्डरों को हटाने के बाद ऊपर रखा गया है, इसका मतलब है 91,92 .... 100 दिन

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

Ex: केवल नवीनतम 30 दिनों की फ़ाइलों के लिए जिन्हें आप हटाना चाहते हैं तो नीचे दिए गए कमांड का उपयोग करें (-)

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

यदि आप 2 दिनों से अधिक फ़ाइलों के लिए फ़ाइलों को प्राप्त करना चाहते हैं

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

यदि आप पिछले एक महीने से केवल फ़ाइलों / फ़ोल्डरों को देखना चाहते हैं। उदाहरण के लिए:

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

30 दिनों से अधिक बाद में केवल फ़ाइलों / फ़ोल्डरों को सूचीबद्ध करें Ex:

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

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

2

मुझे आश्चर्य है कि यहां कोई ulimitजवाब नहीं हैं। जब भी मुझे यह समस्या होती है मैं यहाँ या यहाँ समाप्त होता हूं । मैं समझता हूं कि इस समाधान की सीमाएं हैं, लेकिन ulimit -s 65536लगता है कि यह मेरे लिए अक्सर चाल है।


1

मुझे अस्थायी छवियों से भरे एक फ़ोल्डर के साथ एक ही समस्या थी जो दिन-प्रतिदिन बढ़ रही थी और इस कमांड ने मुझे फ़ोल्डर को साफ करने में मदद की

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

अन्य आदेशों के साथ अंतर mtime पैरामीटर है जो केवल एक्स दिनों की तुलना में पुरानी फ़ाइलों को ले जाएगा (उदाहरण के लिए 50 दिनों में)

उस कई बार का उपयोग करते हुए, दिन के हर निष्पादन पर घटते हुए, मैं सभी अनावश्यक फ़ाइलों को हटाने में सक्षम था


1

मुझे केवल इसके बारे में एक तरीका पता है। विचार यह है कि पीडीएफ फाइलों की सूची आप एक फाइल में निर्यात करें। फिर उस फ़ाइल को कई भागों में विभाजित करें। फिर प्रत्येक भाग में सूचीबद्ध पीडीएफ फाइलों को हटा दें।

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

wc -l को गिनना है कि list.txt में कितनी लाइन है। जब आपके पास यह विचार है कि यह कितना लंबा है, तो आप इसे आधा, आगे या कुछ में विभाजित करने का निर्णय ले सकते हैं। स्प्लिट -l कमांड का उपयोग करना उदाहरण के लिए, इसे 600 लाइनों में विभाजित करें।

split -l 600 list.txt

यह xaa, xab, xac नाम की कुछ फ़ाइल बनाएगा और इस पर निर्भर करेगा कि आप इसे कैसे विभाजित करते हैं। अब कमांड rm में उन फ़ाइल में प्रत्येक सूची को "इम्पोर्ट" करने के लिए, इसका उपयोग करें:

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

मेरी खराब इंग्लिश के लिए माफ़ कीजिये।


5
यदि आपके पास एक फ़ाइल है, तो pdf_format_sucks.docxइसे भी हटा दिया जाएगा ... ;-) आपको पीडीएफ फाइलों के लिए तैयारी करते समय उचित और सटीक नियमित अभिव्यक्ति का उपयोग करना चाहिए।
FooF

1
बेहतर है, लेकिन still_pdf_format_sucks.docxहटा दिया जाएगा। नियमित अभिव्यक्ति .में डॉट ".pdf"किसी भी वर्ण से मेल खाता है। मैं "[.]pdf$"इसके बजाय सुझाव देना चाहूंगा .pdf
FooF

1

मैं कुछ बार इस समस्या में भाग गया। कई समाधान rmप्रत्येक व्यक्तिगत फ़ाइल के लिए कमांड चलाएंगे जिन्हें हटाने की आवश्यकता है। यह बहुत अक्षम है:

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

मैंने फ़ाइल-नाम में पहले 4 वर्णों के आधार पर फ़ाइलों को हटाने के लिए एक अजगर स्क्रिप्ट लिखना समाप्त कर दिया:

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

इसने मेरे लिए बहुत अच्छा काम किया। मैं एक फ़ोल्डर में 2 मिलियन से अधिक अस्थायी फ़ाइलों को लगभग 15 मिनट में साफ़ करने में सक्षम था। मैंने छोटे से कोड के टार पर टिप्पणी की ताकि किसी को भी कम से कम अजगर ज्ञान इस कोड में हेरफेर न कर सके।


1

और दूसरा:

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

printfएक शेल बिल्टिन है, और जहाँ तक मुझे पता है कि यह हमेशा ऐसा ही रहा है। अब यह दिया गया है कि printfएक शेल कमांड (लेकिन एक बिलिन) नहीं है, यह "के अधीन नहीं है"argument list too long ... घातक त्रुटि के ।

इसलिए हम इसे सुरक्षित रूप से शेल ग्लोबिंग पैटर्न के साथ उपयोग कर सकते हैं *.[Pp][Dd][Ff], फिर हम इसके आउटपुट को निकालने के लिए पाइप ( rm) कमांड, थ्रू xargs, जिससे यह सुनिश्चित करता है कि यह कमांड लाइन में पर्याप्त फ़ाइल नाम फिट बैठता है ताकि कमांड को विफल न करें rm, जो कि शेल है आदेश।

\0में printfफ़ाइल नाम जो तब तक कार्रवाई की जाती है के लिए एक अशक्त विभाजक के रूप में सर्व xargsआदेश, इसे का उपयोग ( -0) एक विभाजक के रूप में है, इसलिए rmविफल नहीं हुआ है जब वहाँ सफेद रिक्त स्थान या फ़ाइल नाम में अन्य विशेष वर्ण हैं।


1
हालांकि यह कोड स्निपेट प्रश्न को हल कर सकता है, जिसमें यह भी बताया गया है कि यह समस्या कैसे और क्यों हल करती है वास्तव में आपके पोस्ट की गुणवत्ता को बेहतर बनाने में मदद करेगी । याद रखें कि आप भविष्य में पाठकों के लिए सवाल का जवाब दे रहे हैं, न कि केवल उस व्यक्ति से जो अब पूछ रहा है! कृपया स्पष्टीकरण जोड़ने के लिए अपना उत्तर संपादित करें, और इस बात का संकेत दें कि क्या सीमाएँ और मान्यताएँ लागू होती हैं।
टोबी स्पाइट

विशेष रूप से, यदि printfशेल बिल्ट नहीं है , तो यह उसी सीमा के अधीन होगा।
टोबे स्पाइट

0

आप एक अस्थायी फ़ोल्डर बना सकते हैं, उन सभी फ़ाइलों और उप-फ़ोल्डरों को स्थानांतरित कर सकते हैं जिन्हें आप अस्थायी फ़ोल्डर में रखना चाहते हैं, फिर पुराने फ़ोल्डर को हटा दें और अस्थायी फ़ोल्डर का नाम बदलकर पुराने फ़ोल्डर में करें, जब तक आप इसे लाइव करने के लिए आश्वस्त न हों, तब तक इस उदाहरण का प्रयास करें:

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_folderमें सभी फाइलों को हटा देगा big_folderकोई फर्क नहीं पड़ता कि कितने। आपको बस सुपर सावधान रहना होगा आपके पास पहले सभी फाइलें / फ़ोल्डर हैं जिन्हें आप रखना चाहते हैं, इस मामले में यह थाfile1.pdf


0

*.pdfएक निर्देशिका में सभी को हटाने के लिए/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/

rsyncवाइल्डकार्ड का उपयोग करके विशिष्ट फ़ाइलों को हटाने के लिए संभवत: लाखों फ़ाइलों के मामले में सबसे तेज़ समाधान है। और यह आपके द्वारा की जा रही त्रुटि का ध्यान रखेगा।


(वैकल्पिक चरण): सूखी दौड़। यह जांचने के लिए कि हटाए बिना क्या हटाया जाएगा। `

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

। । ।

अधिक rsync हैक के लिए rsync टिप्स और ट्रिक्स पर क्लिक करें


0

मैंने पाया कि बहुत बड़ी फ़ाइलों की सूची (> 1e6) के लिए, ये उत्तर बहुत धीमे थे। यहाँ अजगर में समानांतर प्रसंस्करण का उपयोग कर एक समाधान है। मुझे पता है, मुझे पता है, यह लिनक्स नहीं है ... लेकिन यहां और कुछ भी काम नहीं किया।

(इससे मेरे घंटे बच गए)

# 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

मैंने एक ऐसी ही समस्या का सामना किया है जब एक एप्लिकेशन द्वारा बनाई गई लाखों बेकार लॉग फाइलें थीं जो सभी इनोड्स को भरती थीं। मैंने "पता लगाने" का सहारा लिया, सभी फ़ाइलों को एक पाठ फ़ाइल में "स्थित" मिला और फिर उन्हें एक-एक करके हटा दिया। थोड़ी देर लगा लेकिन काम कर लिया!


यह बहुत अस्पष्ट है और आपको locateअपनी डिस्क पर कमरा होने पर वापस स्थापित करने की आवश्यकता होती है ।
त्रिपली

-2

ज़ार का उपयोग करने की तुलना में थोड़ा सुरक्षित संस्करण, पुनरावर्ती भी नहीं: ls -p | grep -v '/$' | grep '\.pdf$' | while read file; do rm "$file"; done

यहां हमारी निर्देशिकाओं को फ़िल्टर करना थोड़ा अनावश्यक है क्योंकि 'rm' इसे वैसे भी डिलीट नहीं करेगा, और इसे सरलता के लिए हटाया जा सकता है, लेकिन ऐसा कुछ क्यों चलाएं जो निश्चित रूप से त्रुटि लौटाएगा?


3
यह बिल्कुल भी सुरक्षित नहीं है, और एक स्पष्ट कोने के मामले को इंगित करने के लिए, उन पर नए नामों के साथ फ़ाइल नामों के साथ काम नहीं करता है। पार्सिंगls एक सामान्य एंटीपैटर्न है जिसे निश्चित रूप से टाला जाना चाहिए, और यहां कई अतिरिक्त कीड़े शामिल हैं। यह grep | grepबहुत सुंदर नहीं है।
tripleee

वैसे भी, यह ऐसा नहीं है यह एक नई और विदेशी समस्या है जिसके लिए एक जटिल समाधान की आवश्यकता है। के साथ उत्तर findअच्छे हैं, और यहाँ और अन्य जगहों पर अच्छी तरह से प्रलेखित हैं। उदाहरण के लिए देखें mywiki.wooledge.org इस और संबंधित विषयों पर अधिक जानकारी के लिए।
ट्रिपलआई

-2

GNU समानांतर का उपयोग करना (sudo apt install parallel ) का उपयोग करना बहुत आसान है

यह उन कमांडों को चलाता है जहां '{}' पास किया गया तर्क है

उदाहरण के लिए

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


मुझे नहीं पता, लेकिन मैं इसका अनुमान lsलगाऊंगा क्योंकि अन्य कमांड्स को सीधे आउटपुट देना एक खतरनाक एंटीपैटर्न है - और, यह तथ्य कि वाइल्डकार्ड का विस्तार lsमूल rmकमांड में अनुभव के अनुसार निष्पादित होने पर उसी विफलता का कारण होगा। ।
टोबे स्पाइट

उस पर संदर्भ के लिए, ParsingLs देखें । और parallelकुछ लोगों को बनाता है जो जटिलता से बचना पसंद करते हैं - यदि आप हुड के नीचे देखते हैं, तो यह बहुत अपारदर्शी है। स्टीफन ( Unix और Linux StackExchange greybeards में से एक ) और Oange Tange (समानांतर लेखक) में से एक के रूप में lists.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html पर मेलिंग सूची धागा देखें । यह भी paralellizes, लेकिन यह कम सरल भागों के साथ एक सरल, सुस्त तरीके से करता है, जिससे इसका व्यवहार भविष्यवाणी और तर्क के लिए बहुत आसान हो जाता है। xargs -P
चार्ल्स डफी

-2

पहले 100 फाइलें निकालने के लिए:

rm -rf 'ls | हेड -100 '


2
खतरनाक (या यह होगा कि यदि आप स्पष्ट रूप से इरादा के रूप में backquotes का उपयोग करते हैं) - यदि किसी फ़ाइल नाम में रिक्त स्थान सहित शेल मेटाचैकर शामिल हैं, तो परिणाम वही नहीं होंगे जो आप चाहते थे।
टोबे स्पाइट

-5

नीचे दिया गया विकल्प इस समस्या को सरल लगता है। मुझे यह जानकारी किसी और सूत्र से मिली लेकिन इससे मुझे मदद मिली।

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

बस ऊपर दिए गए एक कमांड को चलाएं और यह कार्य करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.