मैं किसी श्रेणी में गिने हुए फ़ाइलों को कैसे हटा सकता हूं?


16

मेरे पास folderAकुछ फाइलें हैं, जिनके साथ क्रम क्रम शुरू होता है a_000000। मैं एक विशिष्ट संख्या से शुरू होने वाली फ़ाइलों को हटाने के लिए क्या करना चाहता हूं: चलो a_000750इसमें फ़ाइलों के अंत तक कहते हैं folderA। किसी को भी कृपया सलाह दे सकते हैं कि यह शेल स्क्रिप्ट का उपयोग कैसे करें?


क्या मैं मान सकता हूं कि उन सभी फ़ाइलनामों में 6-अंकीय प्रत्यय हैं?
मूरू

हां वे हैं :) वे a_000000 से शुरू होकर कुछ संख्या तक
Tak

5
rm a_000[89]* a_0007[5-9]*?
Rinzwind

@Rinzwind क्या आप इस आदेश की व्याख्या कर सकते हैं?
तक

2
@ user1460166 a_000[89]*के साथ हर फ़ाइल शुरुआत भी शामिल है a_0008या a_0009, और a_0007[5-9]*के साथ शुरुआत हर फ़ाइल शामिल a_0007और उसके बाद 5 से 9 के बीच एक नंबर, कुछ भी के बाद से युक्त।
मूरू

जवाबों:


35

मान लें कि आप जानते हैं या सीमा के अंत का अनुमान लगा सकते हैं, तो आप ब्रेस विस्तार का उपयोग कर सकते हैं :

rm a_{000750..000850}

उपरोक्त a_000750 और a_000850 सम्मिलित के बीच 101 फ़ाइलों को हटा देगा (और फ़ाइल नाम के बारे में शिकायत करता है जो गैर-मौजूदा फ़ाइलों को संदर्भित करता है)। यदि आपके पास उसके लिए बहुत अधिक फाइलें हैं, तो उपयोग करें find:

find . -name 'a_*' | while read file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

यहाँ, findबस सभी फाइलों के मिलान की सूची है a_*। सूची को एक whileलूप में पास किया जाता है जहां प्रत्येक फ़ाइल का नाम चर में पढ़ा जाता है $file। फिर, बैश के स्ट्रिंग मैनिपुलेशन फीचर्स का उपयोग करते हुए , यदि संख्यात्मक भाग (के रूप में फाइल प्रिंट करता है ./file, तो ${file#./a_}केवल संख्या प्रिंट करता है) 000750या अधिक है, फ़ाइल हटा दी जाती है। -vसिर्फ वहाँ है, इसलिए आप देख सकते हैं कि फ़ाइलों को हटा दिया गया।

ध्यान दें कि उपर्युक्त समझदार फ़ाइल नाम हैं। यदि आपके नाम में रिक्त स्थान, नई सूची या अन्य अजीब अक्षर हो सकते हैं, तो इसके बजाय इसका उपयोग करें:

find . -name 'a_*' -print0 | while IFS= read -rd '' file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

क्यों बचें [[?
मुरु

1
@ मरमू इसका उपयोग क्यों करते हैं? उदाहरण के लिए [[यहाँ चीजों को सरल नहीं करता है [[ "${file#./a_}" > 000749 ]], इसे कोई छोटा नहीं बनाता है। मुझे अनावश्यक सिंटैक्स का उपयोग करना पसंद नहीं है और यह सरल जैसे गोले में भी काम करेगा dash
टेराडन

क्योंकि [[रिक्त स्थान और विचित्रताओं को बेहतर तरीके से संभालता है (मैं >या तो परवाह नहीं करता )।
मुरु

1
@ एमरू हाँ, लेकिन [ठीक है यदि आप चर को उद्धृत करते हैं जैसा कि मेरे पास है, कहीं अधिक गोले पर काम करता है और सरल है।
टेराडन

यदि आप कहते है। मेरी समस्या नहीं।
मुरु

3

आप ऐसा कुछ कर सकते हैं:

find . -regextype posix-extended -iregex './a_[0-9]{6}' -execdir bash -c '[[ ${1##./a_} > 000750 ]] && echo $1' "removing: " {} \;

या:

find . -regextype posix-extended -iregex './a_[0-9]{6}' | sort | sed '0,/000750/d' | xargs echo

पहली विधि एक निश्चित उपसर्ग मानती है, इसे बंद कर देती है और मान की जांच करती है।

दूसरी विधि एक निश्चित-लंबाई प्रत्यय (और एक सामान्य निश्चित उपसर्ग) मानती है और उस तथ्य पर निर्भर करती है; और यह कि, जबकि 201पहले 31से ही शाब्दिक रूप से आता है , यह पहले नहीं है 031

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


उनमें से कोई भी काम नहीं कर रहा है: /
Tak

@ user1460166 आह, यह शायद रेगेक्स मिलान के कारण है। मैं इसे अपडेट करूंगा।
मूरू

अभी भी काम नहीं कर रहा है। btw, फाइलें हैं .png :)
Tak

@ user1460166 क्या आप कह सकते हैं कि यह कैसे काम नहीं कर रहा है?
मुरु

मैं टर्मिनल खोलता हूं, फ़ोल्डर में सीडी लगाता हूं, फिर अपनी लाइन कॉपी करता हूं और उसे पेस्ट करता हूं, लेकिन फाइलें डिलीट नहीं होती हैं
Tak

0

POSIX खोल समाधान

टेरडॉन का पहला समाधान ब्रेस विस्तार पर निर्भर करता है, जो की एक संपत्ति है bashऔर ksh, हालांकि इसका उपयोग मानक /bin/shशेल में नहीं किया जा सकता है , जो उबंटू पर सिम्प्लाइड है /bin/dash

ऐसे मामलों में जहाँ आपको /bin/shअपनी स्क्रिप्ट की पोर्टेबिलिटी के लिए निर्भर होना पड़ता है , वहाँ आम तौर पर इस दृष्टिकोण के लिए दो तरीके हैं। एक ग्लोबिंग के माध्यम से होगा। बस cd folderAऔर वहाँ से चला rm a_*। दूसरा तरीका, while <CONDITION>;do ...doneशेल भाषा में लूप के विकल्प के लिए सी-स्टाइल लागू करना और इसके साथ संख्याओं को प्रारूपित करना होगा printf:

$ sh -c 'i=0;while [ $i -le 750 ]; do filename=$(printf "a_%06d" $i);echo "$filename";i=$((i+1)) ;done'

ध्यान दें कि यहां मैं उपयोग करता हूं echo। फ़ाइलों को हटाने के लिए तैयार होने पर या उसके echo "$filename"साथ बदलें । यह भी ध्यान दें, यह तब किया जाना चाहिए जब आप पहले से ही वांछित निर्देशिका में एड करते हैं।rm ./"$filename"rm -- "$filename"cd

(ab) awk का उपयोग करना

Awk एक अच्छी सी-लाइक भाषा होने से हमें दो तरह से मदद मिल सकती है: (1) हम फाइल को लूप के साथ उत्पन्न कर सकते हैं और उन्हें sprintfफंक्शन के माध्यम से फॉर्मेट कर सकते हैं, और (2) system()कमांड के माध्यम से उक्त फाइलों को हटा सकते हैं , जो हमारे उत्पन्न फाइलनाम और rmकमांड को पास करेंगे। को /bin/sh:

awk 'BEGIN{for(i=0;i<=750;i++){filename=sprintf("a_%06d",i);system("rm "filename);} }'

पर्ल

पोर्टेबल दृष्टिकोण के विचार के साथ आगे बढ़ते हुए, जहाँ हम "फ़ाइलनाम" उत्पन्न करते हैं, हम पर्ल में भी ऐसा कर सकते हैं:

perl -le 'for(0..750){$fd=sprintf("a_%06d",$_);unlink($fd)}'

0

की तरह सरल

rm partialfilename* -f

आपके उदाहरण में यह है

rm a_00075* -f

1
कहने के लिए क्षमा करें, लेकिन यह एक सीमा नहीं है, वे सभी फाइलें हैं a_00075...
Fabby

1
* एक वाइल्डकार्ड है, ओपी एक जवाब की तलाश कर रहा है कि चीजों की एक श्रेणी को कैसे हटाया जाए ... उदाहरण के लिए यदि आपके पास 100 के माध्यम से 1 फाइलें थीं, और # 41 को # 75 पर हटाना चाहते थे
जोशुआ बेसनीटे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.