फ़ाइलों को हटाते समय कुछ फ़ाइलों और निर्देशिकाओं को छोड़कर


11

मेरी शीर्ष-स्तरीय निर्देशिका है datadataकई निर्देशिकाएं शामिल हैं और इन निर्देशिकाओं में उप-निर्देशिकाएं हैं। मुझे data/कुछ निर्देशिकाओं में कई फ़ाइलों को छोड़कर सभी फ़ाइलों और निर्देशिकाओं को निकालने की आवश्यकता है ।

उदाहरण के लिए, डेटा में डायरेक्टरी 100और शामिल हैं 101। मैं तो बस रखना चाहते हैं a.txtऔर b.txtमें फ़ाइलों 100/और c.txtऔर d.txtमें फ़ाइलों को 101/थोड़ी देर में अन्य सभी फाइलों और निर्देशिकाओं को हटाने 100और 101

उदाहरण:

.
├── 100
   ├── a.txt
   ├── b.txt
   ├── c.txt
   └── d.txt
└── 101
    ├── a.txt
    ├── b.txt
    ├── c.txt
    └── d.txt

मैं rm -rf !(a.txt|b.txt)कमांड का उपयोग करता हूं लेकिन मैं इस कमांड को प्रत्येक निर्देशिका के लिए स्वचालित रूप से लागू नहीं कर सकता।

जवाबों:


12

जैसा कि आपको पहले ही पता चला है कि आप उस extglobसुविधा का उपयोग कर सकते हैं जो इसके साथ सक्षम है:

shopt -s extglob

यह मैचों को बाहर करने की अनुमति देता है ताकि आप इस तरह की चीजें कर सकें:

rm 100/!([ab].txt) 101/!([cd].txt)

इसका echoपहले परीक्षण करना एक अच्छा विचार है । यह उदाहरण किसी भी चीज से मेल खाएगा 100/जो अंदर नहीं है a.txtया जो b.txtकुछ भी अंदर 101/है c.txtया नहीं है d.txt। यदि 100/लागू होने के लिए समान नियम 102/आप भी कर सकते हैं जैसे:

10[02]/!([ab].txt) # or
{100,102}/!([ab].txt)

मैंने सिर्फ 100 और 101 निर्देशिकाओं के लिए एक उदाहरण दिया है लेकिन वास्तव में उप-निर्देशिकाओं की संख्या लगभग 20 है। क्या प्रत्येक निर्देशिका के लिए मुख्य फ़ोल्डर में प्रत्येक निर्देशिका का नाम लिखे बिना कोड को लागू करने का एक तरीका है?
गहरे रंग

@deepblue कृपया अपने प्रश्न ( संपादित करें ) में इसके लिए एक सटीक उदाहरण प्रदान करें , यह विशेष रूप से अस्पष्ट है कि आपको यह कैसे rmपता होना चाहिए कि कौन सी फाइलों को उन निर्देशिकाओं में रखना है यदि आप इसे निर्दिष्ट नहीं करना चाहते हैं।
मिठाई

7

आप इसके लिए उपयोग कर सकते हैं find। आप में या के findसाथ परीक्षणों को नकार सकते हैं । यह मैच खोजने के बजाय उन्हें बाहर कर देगा।-not!

आपको सावधान रहना चाहिए कि जो भी फाइलें आप रखना चाहते हैं, उनमें से कोई भी मूल निर्देशिका, विशेषकर वर्तमान निर्देशिका . को डिलीट न करें, इसलिए सुनिश्चित करें कि आप डिलीट करने से पहले आउटपुट को अच्छी तरह से पढ़ लें।

अपने उदाहरण के आधार पर आप dataनिर्देशिका से ऐसा कुछ कर सकते हैं ।

find ! -path . ! -path ./100 ! -path ./101 ! -path "./100/[ab].txt" ! -path "./101/[cd].txt"

! -path ./path/to/dirजिस भी पथ से आप हटाना चाहते हैं, उसके लिए जोड़ें । आप जैसे मेटाचट्रैक्टर्स का उपयोग कर सकते हैं *, लेकिन सुनिश्चित करें कि आप अभिव्यक्ति को उद्धृत करते हैं यदि आप करते हैं, जैसे "./path*dir", किसी भी अवांछित विस्तार को रोकने के लिए।

findडिफ़ॉल्ट रूप से पुनरावर्ती है। यहां तक ​​कि अगर हम यहां नहीं पाते ./100हैं, तो हम इसकी सभी सामग्री पाएंगे जब तक कि वे पैटर्न से मेल नहीं खाते [ab].txt। यदि आप उन सभी नामों से मेल नहीं खा सकते हैं जिन्हें आप रखना चाहते हैं, तो एक और परीक्षा जोड़ें:

! -path "./100/[ab].txt" ! -path ./100/foo

यह मिलेगा नहीं a.txtया b.txtया fooहै, लेकिन यह अन्य सभी फ़ाइलों को मिलेगा।

जब आप सुनिश्चित हों कि आप जो चाहते हैं वह देख लें, तो आप -deleteमिली हुई फ़ाइलों को हटाने के लिए अंत में जोड़ सकते हैं :

find ! -path . ! -path ./100 ! -path ./101 ! -path "./100/[ab].txt" ! -path "./101/[cd].txt" -delete
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.