खोजने के लिए -rune विकल्प में कई निर्देशिकाओं को पास करना


9

मैं findबैकअप फ़ाइलों को खोजने और हटाने के लिए उपयोग कर रहा हूं, लेकिन कुछ निर्देशिकाओं को खोज से बाहर करना चाहता हूं। बैकअप फ़ाइल नामों में बंद हो सकता है .bck, bak, ~, या backup

बाहर करने के लिए केवल तीन निर्देशिकाओं वाला न्यूनतम कार्य उदाहरण (MWE) कोड है:

#! /bin/bash
find . -type d \( -path "./.*" -o -path "./Music" -o -path "./Documents" \) -prune -o -type f \( -name "*.bck" -o -name "*.bak" -o -name "*~" -o -name "*.backup" \) -print0 | xargs -0 --no-run-if-empty trash-put

वाक्यविन्यास \( -path "dir1" -o -path "dir2" ... -o -path "dirN" \) -pruneथोड़ा क्लिंकी लगता है, खासकर अगर बाहर करने के लिए लगभग दस निर्देशिकाएं हैं, हालांकि मैंने एमडब्ल्यूई में केवल तीन दिखाए हैं।

क्या बहिष्कृत निर्देशिकाओं की सूची या किसी सरणी- या सूची-जैसे निर्माण के साथ इनपुट फ़ाइल का उपयोग करने का एक और अधिक सुंदर तरीका है, जिसे सेवा में दबाया जा सकता है?

जब मैंने अपना मूल प्रश्न लिखा तो मुझे अधिक स्पष्ट न होने का खेद है।

एनबी: trash-putएक उपयोगिता है जो फ़ाइलों को Trashcanहटाने के बजाय उन्हें स्थानांतरित करती है [1]।

[1]। https://github.com/andreafrancia/trash-cli

जवाबों:


4

जहाँ तक मुझे पता है, findफ़ाइल से पैटर्न पढ़ने का बताने का कोई विकल्प नहीं है । एक आसान तरीका यह है कि उन पैटर्नों को सहेजा जाए जिन्हें मैं किसी फ़ाइल में छोड़ना चाहता हूं और उस फाइल को रिवर्स के लिए इनपुट के रूप में पास करता हूं grep। एक उदाहरण के रूप में, मैंने निम्नलिखित फाइलें और निर्देशिकाएं बनाई हैं:

$ tree -a
.
├── a
├── .aa
├── .aa.bak
├── a.bck
├── b
├── .dir1
│   └── bb1.bak
├── dir2
│   └── bb2.bak
├── b.bak
├── c
├── c~
├── Documents
│   └── Documents.bak
├── exclude.txt
├── foo.backup
└── Music
    └── Music.bak

अगर मैं उदाहरण आप सही तरीके से तैनात समझ में आया, आप ले जाना चाहते a.bck, .aa.bak, b.bak, c~, foo.backupऔर dir2/bb2.bakकचरा और छुट्टी के लिए .aa.bak, .dir1/bb1.bak, Documents/Documents.bakऔर Music/Music.bakकि वे कहाँ हैं। इसलिए, मैंने exclude.txtनिम्नलिखित सामग्रियों के साथ फ़ाइल बनाई है (आप जितना चाहें उतना जोड़ सकते हैं):

$ cat exclude.txt 
./.*/
./Music
./Documents

मैं इसका उपयोग करता हूं ./.*/क्योंकि मैंने आपकी मूल खोज को समझा है कि आप छिपी हुई बैकअप फ़ाइलों ( .foo) को चालू निर्देशिका में ले जाना चाहते हैं, लेकिन छिपी हुई निर्देशिकाओं ( .foo/bar) में किसी भी बैकअप फ़ाइलों को बाहर कर दें । इसलिए, मैं अब अवांछित फ़ाइलों को बाहर करने के लिए findकमांड चला सकता हूं और उपयोग कर सकता हूं grep:

$ find . -type f | grep -vZf exclude.txt | xargs -0 --no-run-if-empty trash-put

Grep विकल्प:

   -v, --invert-match
          Invert  the  sense  of matching, to select non-matching
          lines.  (-v is specified by POSIX.)
   -f FILE, --file=FILE
          Obtain patterns from FILE, one  per  line.   The  empty
          file  contains  zero  patterns,  and  therefore matches
          nothing.  (-f is specified by POSIX.)
   -Z, --null
          Output a zero byte (the ASCII NUL character) instead of
          the  character  that normally follows a file name.  For
          example, grep -lZ outputs a zero byte after  each  file
          name  instead  of the usual newline.  This option makes
          the output unambiguous, even in the  presence  of  file
          names  containing  unusual  characters  like  newlines.
          This  option  can  be  used  with  commands  like  find
          -print0,  perl  -0,  sort  -z,  and xargs -0 to process
          arbitrary file names, even those that  contain  newline
          characters.

मुझे स्पष्ट नहीं होने के लिए बहुत खेद है। कृपया संशोधित प्रश्न देखें जो मुझे आशा है कि स्पष्ट है।
चन्द्र

@ चंद्र का अद्यतन उत्तर, समान सामान्य विचार, विभिन्न विवरण देखें।
terdon

धन्यवाद। आपने मेरे उद्देश्य के लिए मेरे प्रश्न का बहुत स्पष्ट और पूरी तरह से उत्तर दिया है। मैंने आपका उत्तर स्वीकार कर लिया है।
चंद्रा

6

जीएनयू खोजने के साथ (यानी गैर-एम्बेडेड लिनक्स या सिगविन के तहत), आप -regexइन सभी -pathवाइल्डकार्ड को एक एकल रेक्स में संयोजित करने के लिए उपयोग कर सकते हैं ।

find . -regextype posix-extended \
     -type d -regex '\./(\..*|Music|Documents)' -prune -o \
     -type f -regex '.*(\.(bck|bak|backup)|~)' -print0 |
xargs -0 --no-run-if-empty trash-put

FreeBSD या OSX के साथ, के -Eबजाय का उपयोग करें -regextype posix-extended


एक उत्कृष्ट वैकल्पिक उत्तर के लिए धन्यवाद। यह शर्म की बात है कि मैं दो जवाब स्वीकार नहीं कर सकता।
चंद्रा

3

तर्क ( या ) का उपयोग करके -path ... -pruneसंलग्न एक अभिव्यक्ति में समूह ।\( ... \)-o

find /somepath \( -path /a -prune -o \
                  -path /b -prune -o \
                  -path /c -prune \
               \) \
               -o -print

उदाहरण निर्देशिका या फ़ाइलों को या उसके नीचे और /somepath/a, पर पुनरावृति नहीं करेगा ।/somepath/b/somepath/c

यहां कई क्रियाओं का उपयोग करके अधिक विशिष्ट उदाहरण दिया गया है।

find / \( -path /dev -prune -o \
          -path /proc -prune -o \
          -path /sys -prune \
       \) \
       -o -printf '%p ' -exec cksum {} \;

1

यह एक प्रश्न की तुलना में अधिक शेल प्रश्न लगता है find। युक्त फ़ाइल के साथ ( -name dir1 -o -name dir2 ) -prune(कोई "\"!) आप बस ऐसा कर सकते हैं:

find ... $(< /path/to/file)

खोज कॉल को बदलने के बिना ( eval findया $ IFS बदलकर) यह केवल व्हाट्सएप के बिना पथ के साथ काम करता है, हालांकि।

यदि आप फ़ाइल को सरल रखना चाहते हैं तो आप एक स्क्रिप्ट लिख सकते हैं।

# file content
dir1
dir2
dir3

# script content
#!/bin/bash
file=/path/to/file
# file may be checked for whitespace here
grep '[^[:space:]]' "$file" | { empty=yes
  while read dir; do
    if [ yes = "$empty" ]; then
      echo -n "( "
      empty=no
    else
      echo -n " -o "
    fi
    echo -n "-name ${dir}"
  done
  if [ no = "$empty" ]; then
    echo -n " ) -prune"
  fi; }

और उपयोग करें

find ... $(/path/to/script)

बजाय।


मुझे स्पष्ट नहीं होने के लिए बहुत खेद है। कृपया संशोधित प्रश्न देखें जो मुझे आशा है कि स्पष्ट है।
चन्द्र

@chandra मैं देख रहा हूँ न कि कैसे अपने सवाल स्पष्ट है और न ही मैं समझता हूँ कि क्या (की तुच्छ replecement के अलावा मेरी समाधान के साथ एक समस्या हो सकती है -nameके द्वारा path)।
हौके लागिंग

ऊपर मेरी स्क्रिप्ट काम करती है और मैं जो चाहता हूं वह करता हूं। मैं बस यह जानना चाहता था \( -path "dir1" -o -path "dir2" ... -o -path "dirN" \) -pruneकि पुनरावर्ती खोज से कुछ निर्देशिकाओं को बाहर करने की तुलना में एक शून्य तरीका था या findनहीं। मैं फ़ाइलों के भीतर कुछ भी नहीं खोज रहा हूं , बल्कि कुछ फ़ाइलों को हटा रहा हूं और अपने खोज पथ में कुछ निर्देशिकाओं से बच रहा हूं। मुझे समझ नहीं आ रहा है कि आपकी स्क्रिप्ट क्या करने की कोशिश कर रही है। इसलिए, ऐसा प्रतीत होता है कि हमारे पास गलत सूचना है। माफ़ करना। हम उस पर छोड़ दें।
चंद्रा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.