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


11

मेरी शीर्ष-स्तरीय निर्देशिका है data। dataकई निर्देशिकाएं शामिल हैं और इन निर्देशिकाओं में उप-निर्देशिकाएं हैं। मुझे 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.