विशिष्ट नाम वाले एक फ़ोल्डर को छोड़कर सभी फ़ोल्डर हटाएं


18

मुझे दैनिक स्क्रिप्ट का उपयोग करके फ़ोल्डर के अंदर सभी फ़ोल्डर्स को हटाने की आवश्यकता है। उस दिन के फ़ोल्डर को छोड़ना होगा।

फ़ोल्डर 'myfolder' में 3 उप फ़ोल्डर हैं: 'test1', 'test2' और 'test3' मुझे 'test2' को छोड़कर सभी को हटाना होगा।

मैं यहां सटीक नाम से मिलान करने का प्रयास कर रहा हूं:

find /home/myfolder -type d ! -name 'test2' | xargs rm -rf

या

find /home/myfolder -type d ! -name 'test2' -delete

यह कमांड हमेशा मुख्य फ़ोल्डर 'myfolder' को भी हटाने की कोशिश करता है! इससे बचने का कोई रास्ता है क्या ?


6
यूनिक्स और लिनक्स में, हम इन "निर्देशिकाओं" को कहते हैं, "फ़ोल्डर्स" को नहीं।
tchrist

1
आपके शेल के आधार पर, आपको उस !ऑपरेटर को उद्धृत करने की आवश्यकता हो सकती है : \!या '!'
टोबी स्पाईट

जवाबों:


32

यह ./myfolderइसके अलावा सभी फ़ोल्डरों को हटा देगा ./myfolder/test2और इसकी सभी सामग्री संरक्षित रहेगी:

find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?' -delete

यह काम किस प्रकार करता है

  • find एक कमांड शुरू करता है।
  • ./myfolderनिर्देशिका ./myfolderऔर इसकी सामग्री के साथ शुरू करने के लिए कहता है ।

  • -mindepth 1./myfolderखुद से मेल नहीं खाते , इसके तहत सिर्फ फाइलें और निर्देशिका।

  • ! -regex '^./myfolder/test2\(/.*\)?' बताता है !कि नियमित अभिव्यक्ति से मेल खाते किसी भी फ़ाइल या निर्देशिका को बाहर करना ( ) ^./myfolder/test2\(/.*\)?^पथ के नाम की शुरुआत से मेल खाता है। अभिव्यक्ति (/.*\)?या तो मेल खाती है (ए) स्लैश के बाद कुछ भी या (बी) कुछ भी नहीं।

  • -delete बताता है कि मिलान को हटाना (अर्थात गैर-बहिष्कृत) फाइलें।

उदाहरण

एक निर्देशिका संरचना पर विचार करें जो दिखता है;

$ find ./myfolder
./myfolder
./myfolder/test1
./myfolder/test1/dir1
./myfolder/test1/dir1/test2
./myfolder/test1/dir1/test2/file4
./myfolder/test1/file1
./myfolder/test3
./myfolder/test3/file3
./myfolder/test2
./myfolder/test2/file2
./myfolder/test2/dir2

हम -deleteयह देखने के लिए कि क्या मेल खाता है (बिना ) कमांड चला सकते हैं :

$ find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?'
./myfolder/test1
./myfolder/test1/dir1
./myfolder/test1/dir1/test2
./myfolder/test1/dir1/test2/file4
./myfolder/test1/file1
./myfolder/test3
./myfolder/test3/file3

हम सत्यापित कर सकते हैं कि यह काम उन फ़ाइलों को देखकर किया गया है जो बनी हुई हैं:

$ find ./myfolder
./myfolder
./myfolder/test2
./myfolder/test2/file2
./myfolder/test2/dir2

1
उपनिर्देशिकाओं को अकेले -pruneछोड़ने के लिए वैकल्पिक test2/*/: पर वापस जाएँ rm -rऔर जोड़ें -maxdepth 1
टोबी स्पाईट

@ आईसैक ओके। किया हुआ। (इसके अलावा, आपके उत्कृष्ट उत्तर के लिए +1)
जॉन 1024 24

उत्कृष्ट काम !, लेकिन क्षमा करें: जो अंदर सभी फ़ाइलों को हटा देगा ./myfolder। आपको केवल निर्देशिका के-type d लिए एक लापता (IMvhO) की आवश्यकता है ।
NotAnUnixNazi

ठीक है, यह आप के रूप में काम करना चाहिए:find ./myfolder -depth -mindepth 1 -maxdepth 1 -type d ! -regex '^./myfolder/test2\(/.*\)?'
NotAnUnixNazi

10

बैश का उपयोग करना :

shopt -s extglob
rm -r myfolder/!(test2)/

उदाहरण:

$ tree myfolder/
myfolder/
├── test1
│   └── file1
├── test2
│   └── file2
└── test3
    └── file3

$ echo rm -r myfolder/!(test2)
rm -r myfolder/test1 myfolder/test3
$ rm -r myfolder/!(test2)
$ tree myfolder/
myfolder/
└── test2
    └── file2

1 directory, 1 file

5

tl; डॉ

find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 \
     -exec echo rm -rf '{}' \;

फ़ाइलों की सूची से संतुष्ट होने पर प्रतिध्वनि निकालें।


उपयोग करने -mindepth 1से यह सुनिश्चित होगा कि शीर्ष निर्देशिका का चयन नहीं किया गया है।

$ find ./myfolder -mindepth 1 -type d
./myfolder/test2
./myfolder/test2/one
./myfolder/test2/two
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

लेकिन एक -not -name test2होगा नहीं उपनिर्देशिका अंदर से बचने test2:

$ find ./myfolder -mindepth 1 -type d -not -name 'test2'
./myfolder/test2/one
./myfolder/test2/two
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

ऐसा करने के लिए, आपको कुछ कुछ चाहिए जैसे कि prune:

$ find ./myfolder -mindepth 1 -name test2 -prune -o -type d -print
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

लेकिन इसका उपयोग न करें delete, जैसा depthकि इसका तात्पर्य है और यह सबसे लंबे रास्ते से मिटना शुरू हो जाएगा:

$ find ./myfolder -depth -mindepth 1 -name test2 -prune -o -type d -print
./myfolder/test/a1/a2/a3
./myfolder/test/a1/a2
./myfolder/test/a1
./myfolder/test

या तो उपयोग करें rm -rf( echoयदि आप वास्तव में मिटाना चाहते हैं तो हटा दें ):

$ find ./myfolder -mindepth 1 -name test2 -prune -o -type d -exec echo rm -rf '{}' \;
rm -rf ./myfolder/test
rm -rf ./myfolder/test/a1
rm -rf ./myfolder/test/a1/a2
rm -rf ./myfolder/test/a1/a2/a3

या, यह भी का उपयोग maxdepthकरता है, तो आप सभी की जरूरत निर्देशिका (और सब कुछ अंदर) को हटा (दूर करने के लिए है echoवास्तव में मिटा करने के लिए):

$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -exec echo rm -rf '{}' \;
rm -rf ./myfolder/test

-deleteयदि निर्देशिका खाली नहीं है, तब भी A विफल रहेगा:

$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -delete
find: cannot delete ‘./myfolder/test’: Directory not empty

2

यदि आप zsh का उपयोग कर रहे हैं, तो आप कर सकते हैं:

setopt extended_glob # if you don't have it enabled

rm -rf myfolder/^test2

0

नीचे दिए गए आदेश के साथ परीक्षण किया गया और इसने ठीक काम किया

find  /home/myfolder -maxdepth 1 -type d ! -iname test2 -exec rm -rvf {} \;

आप ओपी के रूप में एक ही समस्या में चले गए हैं; कमांड-लाइन (महत्वपूर्ण के बिना -mindepth 1) पर लिस्टिंग / होम / फ़ोल्डर उस शीर्ष निर्देशिका को सभी मानदंडों से मेल खाता है (यह एक निर्देशिका है और इसे "test2" नाम नहीं दिया गया है) और इसलिए यह हटा दिया जाता है।
जेफ स्कालर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.