एक निर्देशिका में सभी फ़ाइलों को पुन: खोज के लिए 'खोज-डिलीट' क्यों करता है


15

इसलिए यूनिक्स का निम्नलिखित व्यवहार मुझे महँगा लगता है:

> touch foo
> touch bar
> ls  
bar  foo
> find . -name '*oo' -delete
> ls
bar
> touch baz
> ls
bar  baz
> find . -delete -name '*ar'
> ls
> #WHAAAT?

इसका अर्थ कैसे निकलता है?


2
यह सवाल संबंधित है, भविष्य के पाठकों के लिए दिलचस्प हो सकता है। unix.stackexchange.com/questions/101282/…
बर्नहार्ड

जवाबों:


14

खोज की कमांड लाइन विभिन्न प्रकार के विकल्पों से बनाई गई है, जो कि अभिव्यक्ति के रूप में संयुक्त हैं।

findविकल्प -deleteएक क्रिया है।
इसका मतलब है कि यह अब तक मिलान की गई प्रत्येक फ़ाइल के लिए निष्पादित किया गया है।
रास्तों के बाद पहले विकल्प के रूप में, सभी फाइलों का मिलान किया जाता है ... उफ़!

यह खतरनाक है - लेकिन मैन पेज कम से कम एक बड़ी चेतावनी है :

से man find:

ACTIONS
    -delete
           Delete  files; true if removal succeeded.  If the removal failed, an
           error message is issued.  If -delete fails, find's exit status  will
           be nonzero (when it eventually exits).  Use of -delete automatically
           turns on the -depth option.

           Warnings: Don't forget that the find command line is evaluated as an
           expression,  so  putting  -delete first will make find try to delete
           everything below the starting points you specified.  When testing  a
           find  command  line  that  you later intend to use with -delete, you
           should explicitly specify -depth in order to avoid later  surprises.
           Because  -delete  implies -depth, you cannot usefully use -prune and
           -delete together.


और आगे से man find:

EXPRESSIONS
    The expression is made up of options (which affect overall operation rather
    than  the  processing  of  a  specific file, and always return true), tests
    (which return a true or false value), and actions (which have side  effects
    and  return  a  true  or false value), all separated by operators.  -and is
    assumed where the operator is omitted.

    If the expression contains no actions other than  -prune,  -print  is  per‐
    formed on all files for which the expression is true.


एक findकमांड क्या करेगी:

यह देखने के लिए कि क्या कमांड पसंद है

find . -name '*ar' -delete

हटा देगा, आप पहले क्रिया -deleteको अधिक हानिरहित क्रिया द्वारा बदल सकते हैं - जैसे -flsया -print:

find . -name '*ar' -print

यह प्रिंट करेगा कि कौन सी फाइलें कार्रवाई से प्रभावित हैं।
इस उदाहरण में, -प्रिंट को छोड़ा जा सकता है। इस मामले में, कोई कार्रवाई नहीं है, इसलिए सबसे स्पष्ट रूप से स्पष्ट रूप से जोड़ा जाता है -print:। (ऊपर उद्धृत "खंड" का दूसरा पैराग्राफ देखें)


मुझे लगता है कि मैं पहले मैनुअल नहीं पढ़ने के लिए सिर्फ एक बेवकूफ था .. लेकिन यह सिर्फ -deleteध्वज जोड़ने के लिए इतना सीधा लग रहा था :-) लेकिन क्या कोई कारण है जो कभी भी किसी और के find . -deleteबजाय होगा rm -rf .? या क्या ऐसा ही होता है जिस तरह से findपर्स और उसके तर्कों को संसाधित करता है?
एमएसज़ेप

1
ओह, मैं इस बात से पूरी तरह सहमत हूं कि वाक्यविन्यास बहुत खतरनाक है - लेकिन इससे बचना कठिन है, क्योंकि यह केवल खोज की कॉमन लाइन एक्सप्रेशन सिंटैक्स का एक विशेष मामला है, जो बेहद शक्तिशाली है। " एक शक्तिशाली चेनसॉ " के रूप में शक्तिशाली
वोल्कर सेगेल

उद्धृत पृष्ठ नहीं कहता है warning: use -depth when testing stuff you later want to -deleteजो आपने अपने व्यावहारिक पक्ष उदाहरण पर नहीं किया है?
pqnet

ओह, ठीक है - समस्या शीर्षक है - मैं एक -nविकल्प की तरह -delete के स्थान पर प्रिंट के उपयोग को स्पष्ट करने के लिए था ; पहले कमांड का बिल्कुल भी व्यावहारिक उपयोग नहीं होना चाहिए; मैं इसे बदल दूँगा।
वोल्कर सिएगेल

9

में findतर्क क्रम मायने रखती है, एक बहुत।

तर्क विकल्प, परीक्षण और कार्य हो सकते हैं। आपको आमतौर पर पहले विकल्पों का उपयोग करना चाहिए, फिर परीक्षण, फिर कार्यों का।

कभी-कभी findआपको संभावित खराब ऑर्डरिंग के बारे में भी चेतावनी देता है (उदाहरण के लिए जब आप -maxdepthअन्य तर्कों के बाद उपयोग करते हैं), लेकिन दूसरों को लगता है कि यह नहीं है।

क्या find . -delete -name '*ar'है:

  1. वर्तमान निर्देशिका पर फ़ाइलों और निर्देशिकाओं को ढूँढता है।
  2. वे सभी को नष्ट कर दिया जाता है क्योंकि वे पाए जाते हैं!
  3. फिर देखता है कि क्या उन्हें '* ar' नाम दिया गया है (इस हिस्से का अब कोई प्रभाव नहीं है)।

आप शायद क्या करना चाहते हैं:

find -name '*ar' -delete

यह, प्रत्येक फ़ाइल के लिए, यह देखेगा कि क्या यह मेल खाता है '*ar', और केवल अगर यह शर्त को पूरा करता है तो यह फ़ाइल को हटा देगा।

क्षमा करें यदि आपको बहुत देर से पता चला।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.