आप शायद मतलब है "अनुमति से वंचित" - जो find
उबंटू में आपको दिखाता है जब आप फ़ाइल अनुमतियों के कारण कुछ का उपयोग नहीं कर सकते हैं - बजाय "अस्वीकृत"।
एक पूरी तरह से सामान्य कमांड जो इसे सही ढंग से करता है (और, बोनस के रूप में, अन्य * nix es के लिए पोर्टेबल है , जब तक कि त्रुटि संदेश समान है):
(find 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied') 3>&1 1>&2 2>&3 3>&-
(आमतौर पर आप कुछ तर्क पारित करना चाहते हैं find
। वे पहले पुनर्निर्देशन से पहले जाते हैं 3>&1
।)
हालांकि, अक्सर आप कुछ सरल उपयोग करने में सक्षम होंगे। उदाहरण के लिए, आप संभवतः प्रक्रिया प्रतिस्थापन का उपयोग कर सकते हैं । विवरण का पालन करें।
सबसे आम तरीके और उनकी सीमाएँ
दो विशिष्ट दृष्टिकोण स्टडर्र ( ज़न्ना के जवाब के रूप में ) को फेंकने के लिए या stdout को फ़िल्टर करने और stdout को फ़िल्टर करने के लिए पुनर्निर्देशित करना है (जैसा कि एंड्रॉइड देव के उत्तर में है )। यद्यपि उन्हें लिखने में सरल होने का लाभ है और अक्सर उचित विकल्प होते हैं, ये दृष्टिकोण आदर्श नहीं हैं।
Stderr -such को भेजी गई सभी चीजों को डिस्कनेक्ट करने के साथ - साथ या इसे "अनुमति अस्वीकार" के अलावा लापता त्रुटियों के जोखिम के साथ-साथ इसे बंद करके इसे null डिवाइस पर भेज दिया जाता है ।2>/dev/null
2>&-
"अनुमति से वंचित" संभवतः दौड़ते समय देखी जाने वाली सबसे आम त्रुटि है find
, लेकिन यह एकमात्र संभावित त्रुटि से दूर है, और यदि कोई अन्य होता है, तो आप इसके बारे में जानना चाह सकते हैं। विशेष रूप से, find
रिपोर्ट "कोई ऐसी फ़ाइल या निर्देशिका नहीं" यदि कोई प्रारंभिक बिंदु मौजूद नहीं है। कई शुरुआती बिंदुओं के साथ, find
अभी भी कुछ उपयोगी परिणाम वापस कर सकते हैं और काम करने के लिए प्रकट हो सकते हैं। उदाहरण के लिए, यदि मौजूद है a
और नहीं है , तो परिणाम प्रिंट करता है , तो इसके लिए "ऐसी कोई फ़ाइल या निर्देशिका" नहीं है , फिर परिणाम होता है ।c
b
find a b c -name x
a
b
c
Stdout में stdout और stderr का मेल एक साथ और यह पाइप के लिए grep
या कुछ अन्य आदेश के साथ के रूप में यह-फिल्टर करने के लिए 2>&1 | grep ...
या |& grep ...
अनजाने एक फ़ाइल जिसका नाम संदेश फ़िल्टर किए जा रहे होते हैं को छान के जोखिम -runs।
उदाहरण के लिए, यदि आप "अनुमति अस्वीकृत" वाली पंक्तियों को फ़िल्टर करते हैं, तो आप "अनुमति अस्वीकृत संदेश.txt" जैसे फ़ाइल नाम दिखाते हुए खोज परिणाम भी छोड़ देंगे। यह संभवत: दुर्घटना से होगा, हालांकि यह एक फ़ाइल के लिए भी संभव होगा कि आपकी खोजों को विफल करने के लिए विशेष रूप से तैयार नाम दिया जाए।
संयुक्त धाराओं को फ़िल्टर करने की एक और समस्या है, जिसे अधिक चुनिंदा तरीके से फ़िल्टर करके कम नहीं किया जा सकता है (जैसे grep -vx 'find: .*: Permission denied'
कि पाइप के दाईं ओर)। जब आप कोई कार्रवाई निर्दिष्ट नहीं करते हैं, तो निहित कार्रवाई find
सहित कुछ क्रियाएं -print
निर्धारित करती हैं कि कैसे stdout टर्मिनल है या नहीं, इसके आधार पर फाइलनाम का उत्पादन किया जाता है।
- यदि यह टर्मिनल नहीं है, तो फ़ाइल नाम आउटपुट हैं-भले ही वे नए वर्णों और नियंत्रण वर्णों की तरह अजीब वर्ण हैं जो आपके टर्मिनल के व्यवहार को बदल सकते हैं। यदि यह है एक टर्मिनल है, तो इन पात्रों को दबा दिया जाता है और
?
बजाय छपा है।
- यह आमतौर पर आप क्या चाहते हैं। यदि आप फ़ाइल नाम को आगे संसाधित करने जा रहे हैं, तो उनका शाब्दिक रूप से आउटपुट होना चाहिए। हालाँकि, यदि आप उन्हें प्रदर्शित करने जा रहे हैं, तो एक नई नाम के साथ एक फ़ाइल नाम अन्यथा कई फ़ाइल नाम की नकल कर सकता है, और बैकस्पेस वर्णों के अनुक्रम के साथ एक फ़ाइल नाम एक अलग नाम हो सकता है। अन्य समस्याएं भी संभव हैं, जैसे कि फ़ाइल नाम जिसमें एस्केप सीक्वेंस हैं जो आपके टर्मिनल में रंग बदलते हैं।
- लेकिन खोज परिणाम को किसी अन्य कमांड (जैसे
grep
) के माध्यम से पाइप करने से find
टर्मिनल देखने में कोई दिक्कत नहीं होती है। (अधिक सटीक रूप से, यह इसके स्टडआउट को टर्मिनल नहीं बनाने का कारण बनता है।) तब अजीब अक्षर आउटपुट होते हैं। लेकिन अगर पाइप के दाईं ओर सभी कमांड है (ए) "अनुमति से इनकार" संदेशों की तरह दिखने वाली लाइनों को हटा दें और (बी) प्रिंट क्या बचा है, तो आप अभी भी शेंनिगन्स के प्रकार के अधीन हैं जो कि find
टर्मिनल है रोकने का इरादा है।
man find
फ़ाइल नाम प्रिंट करने वाली प्रत्येक क्रिया के व्यवहार सहित अधिक जानकारी के लिए UNUSUAL FILENAMES अनुभाग देखें । ( "डेटा के मुद्रण अन्य उपयोगकर्ताओं के नियंत्रण में है, जिसमें खोज परिणाम की कार्रवाई ... से कई" ) यह भी देखें वर्गों 3.3.2.1 , 3.3.2.2 , और 3.3.2.3 के जीएनयू Findutils संदर्भ मैनुअल ।
असामान्य फाइलनामों की उपरोक्त चर्चा जीएनयू से संबंधित है , जो find
उबुनू सहित जीएनयू / लिनक्स सिस्टम में कार्यान्वयन है।
मानक त्रुटि को फ़िल्टर करते समय अकेले मानक आउटपुट छोड़ना
क्या आप वास्तव में यहाँ चाहते हैं छोड़ने के लिए है stdout जबकि पाइप बरकरार stderr करने के लिए grep
। दुर्भाग्य से इसके लिए कोई सरल वाक्यविन्यास नहीं है। |
पाइप stdout, और कुछ शैलें (सहित bash
) |&
दोनों धाराओं को पाइप करने के लिए समर्थन करती हैं - या आप stdout को पहले stderr पर पुनर्निर्देशित कर सकते हैं 2>&1 |
, जिसका प्रभाव समान है। लेकिन आमतौर पर इस्तेमाल किए जाने वाले गोले केवल पाइप्डर को सिंटैक्स प्रदान नहीं करते हैं।
आप अभी भी ऐसा कर सकते हैं। यह सिर्फ अजीब है। एक तरीका स्टडर के साथ स्टैडआउट स्वैप करना है , ताकि खोज परिणाम स्टॉडर पर हों और स्टडआउट में त्रुटियां हों, फिर grep
फ़िल्टरिंग के लिए पाइप स्टडआउट करें :
find args 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied'
आमतौर पर आप तर्कों को पास करेंगे find
, जैसे कि शुरुआती बिंदु (खोज करने के लिए स्थान, जो आमतौर पर निर्देशिकाएं हैं) और भविष्यवाणी (परीक्षण और क्रियाएं)। ये args
ऊपर के स्थान पर जाते हैं।
यह दो मानक धाराओं में से एक जिसे आप स्वैप करना चाहते हैं, उन्हें स्वैप करने के लिए पुनर्निर्देशन और नई फ़ाइल विवरणक को बंद करने के लिए एक नई फ़ाइल डिस्क्रिप्टर को पेश करने से काम करता है ।
- फ़ाइल वर्णनकर्ता 1 stdout है और 2 stderr है (और unredirected 0 है stdin )। लेकिन आप अन्य फ़ाइल डिस्क्रिप्टर का उपयोग करके भी पुनर्निर्देशित कर सकते हैं। इसका उपयोग किसी फ़ाइल या डिवाइस को खोलने, या खुले रखने के लिए किया जा सकता है।
3>&1
फ़ाइल डिस्क्रिप्टर 3 को stdout में रीडायरेक्ट करता है, ताकि जब stdout (फ़ाइल डिस्क्रिप्टर 1) को बाद में रीडायरेक्ट किया जाए, तो मूल स्टडआउट को आसानी से लिखा जा सकता है।
1>&2
Stdout को stderr पर पुनर्निर्देशित करता है। चूंकि फाइल डिस्क्रिप्टर 3 अभी भी मूल स्टडआउट है, फिर भी इसे एक्सेस किया जा सकता है।
2>&3
डिस्क्रिप्टर 3 को फाइल करने के लिए stderr को रीडायरेक्ट करता है, जो कि मूल स्टडआउट है।
3>&-
फ़ाइल डिस्क्रिप्टर 3 को बंद कर देता है, जिसकी अब आवश्यकता नहीं है।
- अधिक जानकारी के लिए, देखें कैसे stderr पाइप, और stdout नहीं? और IO पुनर्निर्देशन - स्वैपिंग stdout और stderr (उन्नत) और विशेष रूप से केवल फिल्टर के माध्यम से stderr पाइप ।
हालाँकि, इस पद्धति का नुकसान यह है कि खोज के परिणाम stderr को भेजे जाते हैं और त्रुटियों को stdout में भेजा जाता है । यदि आप इस कमांड को सीधे एक इंटरैक्टिव शेल में चला रहे हैं और आउटपुट को आगे किसी भी तरह से पाइपिंग या रीडायरेक्ट नहीं कर रहे हैं, तो यह वास्तव में मायने नहीं रखता है। अन्यथा, यह एक समस्या हो सकती है। यदि आप उस कमांड को स्क्रिप्ट में रखते हैं, और फिर कोई (शायद आप, बाद में) इसके आउटपुट को रीडायरेक्ट या पाइप करता है, तो यह अपेक्षित व्यवहार नहीं करता है ।
समाधान यह है कि आप आउटपुट को फ़िल्टर करने के बाद धाराओं को वापस स्वैप करें । पाइप लाइन के दाईं ओर ऊपर दिखाए गए समान रीडायरेक्शन को लागू करने से यह हासिल नहीं होगा, क्योंकि |
केवल पाइप ही स्टडआउट करते हैं, इसलिए पाइप लाइन के उस हिस्से को केवल आउटपुट प्राप्त होता है जो मूल रूप से stderr को भेजा गया था (क्योंकि धाराएँ बदली गई थीं) और मूल नहीं स्टडआउट आउटपुट। इसके बजाय, आप उप-(
)
कमांड ( संबंधित ) में चलाने के लिए उपयोग कर सकते हैं , फिर उस पर स्वैपिंग पुनर्निर्देशन लागू कर सकते हैं:
(find args 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied') 3>&1 1>&2 2>&3 3>&-
यह समूहीकरण है, विशेष रूप से उपधारा नहीं है, जो यह काम करता है। यदि आप चाहें, तो आप उपयोग कर सकते हैं {
;}
:
{ find args 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied'; } 3>&1 1>&2 2>&3 3>&-
एक कम बोझिल तरीका: प्रक्रिया प्रतिस्थापन
सिस्टम पर बैश सहित कुछ गोले, जो इसका समर्थन कर सकते हैं (उबंटू की तरह जीएनयू / लिनक्स सिस्टम सहित), आप प्रक्रिया प्रतिस्थापन करते हैं , जो आपको एक कमांड चलाने और इसकी एक धारा से / पर रीडायरेक्ट करने की अनुमति देता है। आप find
कमांड के स्टडर को एक grep
कमांड को रीडायरेक्ट कर सकते हैं , जो इसे फिल्टर करता है, और उस grep
कमांड के स्टडआउट को स्टेडर में रीडायरेक्ट करता है ।
find args 2> >(grep -Fv 'Permission denied' >&2)
इस विचार का श्रेय Android देव को जाता है।
हालांकि उबंटू में प्रक्रिया प्रतिस्थापन bash
का समर्थन करता है , जो नहीं है। यदि आप इस विधि का उपयोग करने का प्रयास करते हैं, तो यह आपको "सिंटैक्स त्रुटि: पुनर्निर्देशन अप्रत्याशित" देगा, जबकि स्टैडआउट और स्टैडर को स्वैप करने की विधि अभी भी काम करेगी। इसके अलावा, जब POSIX मोड में चलता है , प्रक्रिया प्रतिस्थापन के लिए समर्थन बंद है।sh
dash
bash
bash
POSIX मोड में चलने वाली एक स्थिति तब होती है जब इसे sh
1 के रूप में लागू किया जाता है । इसलिए, फेडोरा जैसे एक ओएस पर जहां bash
प्रदान करता है /bin/sh
, या यदि आपने उबंटू पर खुद /bin/sh
को सिमलिंक बिंदु बनाया है bash
, तो प्रक्रिया प्रतिस्थापन sh
एक पूर्व स्क्रिप्ट में काम नहीं करता है , बिना पूर्व आदेश के पॉसिक्स मोड को बंद करने के लिए। यदि आप पहले से ही नहीं हैं तो आपका सबसे अच्छा दांव, अगर आप इस विधि का उपयोग स्क्रिप्ट में करना चाहते हैं , तो इसके बजाय #!/bin/bash
शीर्ष पर रखना है #!/bin/sh
।
1 : इस स्थिति में, अपने स्टार्टअप स्क्रिप्ट में कमांड चलाने के बादbash
POSIX मोड अपने आप चालू हो जाता है ।
एक उदाहरण
इन आदेशों का परीक्षण करने में सक्षम होना उपयोगी है। ऐसा करने के लिए, मैं tmp
वर्तमान निर्देशिका का एक उपनिर्देशिका बनाता हूं और इसे कुछ फ़ाइलों और निर्देशिकाओं के साथ पॉप्युलेट करता हूं , जिससे "अनुमति अस्वीकृत" त्रुटि को ट्रिगर करने के लिए उनमें से किसी एक से अनुमति लेते हुए find
।
mkdir tmp; cd tmp; mkdir a b c; touch w a/x 'a/Permission denied messages.txt' b/y c/z; chmod 0 b
निर्देशिका है कि में से एक है सुलभ के साथ "अनुमति अस्वीकृत" अपने नाम में एक फाइल भी शामिल है। find
बिना रीडायरेक्शंस या पाइप के साथ चलना इस फ़ाइल को दिखाता है, लेकिन वास्तविक "अनुमति से वंचित" त्रुटि को किसी अन्य निर्देशिका के लिए दिखाता है जो सुलभ नहीं है:
ek@Io:~/tmp$ find
.
./a
./a/Permission denied messages.txt
./a/x
./c
./c/z
./w
./b
find: ‘./b’: Permission denied
grep
"अनुमति से वंचित" होने वाली पंक्तियों को stdout और stderr दोनों को पाइप करने और फ़िल्टर करने से त्रुटि संदेश चला जाता है, लेकिन फ़ाइल के लिए खोज परिणाम को उसके नाम में छिपा देता है:
ek@Io:~/tmp$ find |& grep -Fv 'Permission denied'
.
./a
./a/x
./c
./c/z
./w
./b
find 2>&1 | grep -Fv 'Permission denied'
समतुल्य है और समान उत्पादन करता है।
"अनुमति अस्वीकृत" को केवल त्रुटि संदेशों से फ़िल्टर करने के लिए ऊपर दिखाए गए तरीके - और खोज परिणामों से नहीं - सफल हैं। उदाहरण के लिए, यहाँ वह विधि है जहाँ stdout और stderr की अदला-बदली की जाती है:
ek@Io:~/tmp$ (find 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied') 3>&1 1>&2 2>&3 3>&-
.
./a
./a/Permission denied messages.txt
./a/x
./c
./c/z
./w
./b
find args 2> >(grep -Fv 'Permission denied' >&2)
वही उत्पादन करता है।
आपको लगता है कि लाइनों को stderr करने के लिए भेजा है कि यह सुनिश्चित करने के लिए एक अलग त्रुटि संदेश ट्रिगर कर सकते हैं नहीं है पाठ "अनुमति अस्वीकृत" शामिल अभी भी के माध्यम से की अनुमति है। उदाहरण के लिए, यहां मैं एक प्रारंभिक बिंदु के रूप find
में वर्तमान निर्देशिका ( .
) के साथ चला हूं , लेकिन कोई foo
अन्य के रूप में अनुपलब्ध निर्देशिका :
ek@Io:~/tmp$ (find . foo 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied') 3>&1 1>&2 2>&3 3>&-
.
./a
./a/Permission denied messages.txt
./a/x
./c
./c/z
./w
./b
find: ‘foo’: No such file or directory
जाँच है कि find
मानक उत्पादन अभी भी एक टर्मिनल है
हम यह भी देख सकते हैं कि कौन से कमांड विशेष वर्णों का कारण बनते हैं, जैसे कि नई रूपरेखाओं को शाब्दिक रूप से प्रदर्शित किया जाना है। (यह ऊपर के प्रदर्शन से अलग किया जा सकता है, और इसे tmp
निर्देशिका में होने की आवश्यकता नहीं है ।)
इसके नाम में एक नई रेखा के साथ एक फ़ाइल बनाएँ:
touch $'abc\ndef'
आमतौर पर हम निर्देशिकाओं का उपयोग शुरुआती बिंदुओं के लिए करते हैं find
, लेकिन फाइलें भी काम करती हैं:
$ find abc*
abc?def
एक और आदेश के लिए stdout पाइप का कारण बनता है न्यू लाइन सचमुच outputted किया जाना है, के दो अलग-अलग खोज परिणाम गलत धारणा बनाने abc
और def
। हम इसके साथ परीक्षण कर सकते हैं cat
:
$ find abc* | cat
abc
def
सिर्फ stderr को पुनर्निर्देशित करने से यह समस्या उत्पन्न नहीं होती है:
$ find abc* 2>/dev/null
abc?def
न ही इसे बंद करना:
$ find abc* 2>&-
abc?def
करने के लिए पाइप grep
करता समस्या कारण:
$ find abc* |& grep -Fv 'Permission denied'
abc
def
(के |&
साथ बदलने के 2>&1 |
बराबर है और एक ही उत्पादन पैदा करता है।)
Stdout और Stderr और पाइपिंग Stdout को स्वैप करने से समस्या पैदा नहीं होती find
है- Stdout stderr हो जाता है, जो पाइप नहीं किया जाता है :
$ find abc* 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied'
abc?def
उस कमांड को ग्रुप करना और स्ट्रीम को स्वैप करने से समस्या उत्पन्न नहीं होती है:
$ (find abc* 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied') 3>&1 1>&2 2>&3 3>&-
abc?def
( {
;}
संस्करण समान आउटपुट का उत्पादन करता है।)
स्टीडर को फ़िल्टर करने के लिए प्रक्रिया प्रतिस्थापन का उपयोग करने से समस्या का कारण नहीं बनता है:
$ find abc* 2> >(grep -Fv 'Permission denied' >&2)
abc?def