खोज: prune निर्दिष्ट पथ की उपेक्षा नहीं करता है


13

मुझे .gitअपनी findखोज से बाहर करने की आवश्यकता है । यह प्राप्त करने के लिए, मैं -path ./.git -pruneस्विच का उपयोग कर रहा हूं :

$ find . -path ./.git -prune -o \( -type f -o -type l -o -type d \) | grep '.git'
./.git

हालाँकि, भले ही यह .गित निर्देशिका की सामग्री को छोड़ देता है, यह निर्देशिका को ही सूचीबद्ध करता है। जब मैं जोड़ता हूं तो यह काम करता है-path ./.git -prune -o -print -a

find . -path ./.git -prune -o -print -a \( -type f -o -type l -o -type d \) | grep '.git'

यह क्यों आवश्यक है मुझे लगा कि दोनों कमांड का आउटपुट समान होना चाहिए। दूसरा सिंटैक्स काफी बदसूरत है।


4
आपको एक की आवश्यकता है -print, अन्यथा निहित -printपूरी स्थिति पर लागू होता है
स्टीफन चेज़लस


जवाबों:


3

manके लिए पेज findदेता है:

-prune True; if the file is a directory, do not  descend  into  it.  If
      -depth  is  given,  false;  no  effect.  Because -delete implies
      -depth, you cannot usefully use -prune and -delete together.

इसलिए पहले उदाहरण में ऐसा नहीं है कि -path ./.git -pruneयह असत्य है और इसलिए डिफ़ॉल्ट कार्रवाई ( -print) नहीं कहा जाएगा, इसलिए लाइन मुद्रित है।


22

मैं इस उलझन में था कि क्यों छंटनी निर्देशिकाओं को findकमांड द्वारा मुद्रित किया जा रहा है , भी, और कुछ अन्य जटिल विवरण कैसे -pruneकाम करते हैं, लेकिन कुछ उदाहरणों के साथ यह पता लगाने में सक्षम था।

नीचे दिए गए उदाहरणों को चलाने के लिए निम्नलिखित निर्देशिका और फाइलें बनाएं।

mkdir aa
mkdir bb
touch file1
touch aa/file1
touch bb/file3

इस संरचना को बनाने के लिए:

$ tree

.
├── aa
   └── file1
├── bb
   └── file3
└── file1

अब निर्देशिकाओं के नाम खोजने के लिए उपयोग करें aa। यहाँ कोई समस्या नहीं है।

$ find . -type d -name aa
./aa

आ के अलावा सभी निर्देशिकाओं को देखें और हमें वर्तमान निर्देशिका मिलती है .और ./bbइससे भी समझ में आता है।

$ find . -type d ! -name aa
.
./bb

अब तक बहुत अच्छा है, लेकिन जब हम उपयोग करते हैं -prune, तो उस निर्देशिका को वापस पाते हैं जिसे हम छंटाई कर रहे हैं, जिसने शुरू में मुझे भ्रमित कर दिया था क्योंकि मैं उम्मीद कर रहा था कि यह सभी अन्य निर्देशिकाओं को लौटाएगी न कि किसी को चुभने वाली।

$ find . -type d -name aa -prune
./aa

इसका कारण यह है कि निर्देशिका को वापस लौटाया जा रहा है, -pruneजिसे तिमो के उत्तर में इंगित किए गए मैन पेजों के अनुभाग में नहीं, बल्कि अनुभाग में समझाया गया है EXPRESSIONS:

यदि अभिव्यक्ति के अलावा कोई क्रिया नहीं है -prune,  तो -printउन सभी फ़ाइलों पर किया जाता है जिनके लिए अभिव्यक्ति सत्य है।

जिसका अर्थ है कि, चूंकि अभिव्यक्ति aaनिर्देशिका नाम से मेल खाती है , तो अभिव्यक्ति सही का मूल्यांकन करेगी और इसे मुद्रित किया जाएगा क्योंकि -printसंपूर्ण कमांड के अंत में निहित रूप से जोड़ते हैं । -printयदि आप जानबूझकर कार्रवाई -o -printको अंत में खुद से जोड़ते हैं, तो यह एक जोड़ नहीं देगा :

find . -type d -name aa -prune -o -print
.
./file1
./bb
./bb/file3

यहां खोज आदेश -printअब एक निहित नहीं जोड़ते हैं, और इसलिए जिस निर्देशिका को हम छंटनी कर रहे हैं ( aa) मुद्रित नहीं होगी।

तो अंत में, यदि हम एक ऐसा क्लॉज जोड़ते हैं जो फाइल्स के पैटर्न फाइल फाइल के साथ खोजता file*है -o, तो आपको -printउस दूसरे क्लॉज के अंत में इस तरह रखना होगा:

find . \( -type d -name aa -prune \) -o \( -type f -name 'file*' -print \)
./file1
./bb/file3

कारण यह है कि यह कार्य समान है: यदि आप -printदूसरे खंड में नहीं डालते हैं , तो चूंकि कार्रवाई के अलावा कोई कार्रवाई नहीं -pruneहै, -printइसलिए कमांड के END में स्वचालित रूप से जोड़ देगा , जिससे -pruneखंड प्रिंट हो जाएगा छंटाई की गई निर्देशिका:

find . \( \( -type d -name aa -prune \) -o \( -type f -name 'file*' \) \) -print
./aa
./file1
./bb/file3

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

find . \( -type d -name aa -prune -o -print \) -o \( -type f -name 'file*' \)
.
./file1
./bb
./bb/file3

इसलिए दुर्भाग्य से, मूल पोस्टर को -printगलत जगह रखकर ऊपर गलत आदेश मिला । यह उनके विशिष्ट मामले के लिए काम कर सकता है, लेकिन यह सामान्य मामले में काम नहीं करता है।

ऐसे हजारों लोग हैं जिन्हें समझने में कठिनाई होती है कि कैसे -pruneकाम करता है। findआदमी पृष्ठ इस आदेश के बारे में neverending दुनिया भर में भ्रम की स्थिति को रोकने के लिए अद्यतन किया जाना चाहिए।


मेरा मैन पेज (आर्क लिनक्स find-4.6.0) , कहता है, "यदि संपूर्ण अभिव्यक्ति में कोई अन्य क्रियाएँ नहीं हैं, तो -प्रिंट या -प्रिंट, -प्रिंट सभी फाइलों पर किया जाता है, जिसके लिए पूरी अभिव्यक्ति सत्य है।" लेकिन जैसा आप वर्णन करते हैं वैसा ही काम करता है।
एक्स-यूरी

0

से manपेज,

एक पूरी निर्देशिका ट्री को अनदेखा करने के लिए, ट्री में प्रत्येक फ़ाइल की जाँच करने के बजाय -prune का उपयोग करें। उदाहरण के लिए, निर्देशिका `src / emacs 'और इसके अंतर्गत आने वाली सभी फ़ाइलों और निर्देशिकाओं को छोड़ें, और मिली अन्य फ़ाइलों के नाम प्रिंट करें, ऐसा कुछ करें:

find . -path ./src/emacs -prune -o -print

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

find . -path ./.git -prune -o -print

यह .gitनिर्देशिका को सूचीबद्ध नहीं करेगा ।

एक फ़ाइल नाम विशिष्ट करने के लिए, आप इस तरह कर सकते हैं:

find . -path ./.git -prune , -name filename

कृपया ,अल्पविराम ऑपरेटर को नोटिस करें ।


-1

यहाँ एक त्वरित और गंदा विकल्प है:

find | fgrep -v /.git

मैं बस findजटिल वाक्यविन्यास याद नहीं कर सकते ...

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