कभी-कभी इसकी कमांड लाइन पथ तर्क से क्यों मिलती है?


9

लिनक्स पर,

cd /tmp
mkdir foo; cd foo

अब चल रहा है

find . -name 'foo'

कोई आउटपुट नहीं देता। जबकि चल रहा है

find /tmp/foo -name 'foo'

आउटपुट देता है /tmp/fooजो मेरे लिए समझ में नहीं आता है। कोई समझा सकता है क्यों?


2
लगता है के रूप में यह कहा गया है शामिल दिए गए पथ के अंदर seaches। इसलिए यदि आप इनपुट ./करते हैं तो यह मेल नहीं खाताfoo
कोस्टास

@ कोस्टस: मैं समझता हूं कि। मुझे समझ में नहीं आता है कि अगर मैं पूर्ण मार्ग देता हूं तो इससे क्या फर्क पड़ा है find
यॉर्क

@York कुछ स्थितियों में कोई ऐसा व्यवहार नहीं है जो हमेशा सही हो। उस नाम के साथ एक सिम्लिंक की कल्पना करें जो barएक फ़ाइल की ओर इशारा fooकरता है जो खोज पथ के बाहर है। मैच होगा या नहीं?
हौके लैजिंग

1
.और /tmp/fooएक ही नहीं हैं - वे एक ही निर्देशिका में दो अलग-अलग हार्ड लिंक कर रहे हैं; find /tmp/foo/. -name 'foo'कुछ भी नहीं पाता है।
जिमीज

@ जिमीज: जब मैं दौड़ता हूं find /tmp/foo -name 'foo', तो मैं निर्देशिका में खोजने के लिए बैश पूछ रहा था /tmp/foo, एक फाइल जिसका नाम "फू" है। क्योंकि निर्देशिका /tmp/fooखाली है, उसे कुछ भी नहीं लौटाना चाहिए था। मुझे समझ नहीं आता कि यह क्यों लौटता है /tmp/foo। दूसरी ओर, जब मैं दौड़ता हूं, तो मैं find . -name 'foo'एक ही चीज़ को बैश करने के लिए कह रहा था, यानी, वर्तमान निर्देशिका (जो हुआ /tmp/foo) में एक फ़ाइल ढूंढ रहा है , जिसका नाम 'फू' है, और यह कुछ भी नहीं देता है जो समझ में आता है।
यॉर्क

जवाबों:


15

findनिर्दिष्ट निर्देशिका ट्री (ओं) का पता लगाता है, और प्रत्येक फ़ाइल के लिए दी गई अभिव्यक्ति का मूल्यांकन करता है जो इसे पाता है। ट्रैवर्सल दिए गए रास्ते पर शुरू होता है। यहां बताया गया है कि कैसे find . -name fooकाम करता है:

  • कमांड लाइन पर पहला रास्ता: .
    • क्या आधार नाम ( .) पैटर्न से मेल खाता है foo? नहीं, तो कुछ मत करो।
      ऐसा होता है कि /tmp/fooउसी निर्देशिका के लिए एक और नाम है। लेकिन findवह नहीं जानता (और यह पता लगाने की कोशिश नहीं की जाती है)।
    • क्या मार्ग एक निर्देशिका है? हां, तो इसे पीछे छोड़ दें। प्रविष्टियों में .प्रवेश करें, और प्रत्येक प्रविष्टि के लिए, ट्रैवर्सल प्रक्रिया करें।
      • निर्देशिका खाली है: इसमें इसके अलावा कोई प्रविष्टि नहीं है .और .., जो findपुनरावृत्ति नहीं करता है। तो काम ख़त्म।

और find /tmp/foo:

  • कमांड लाइन पर पहला रास्ता: /tmp/foo
    • क्या आधार नाम ( foo) पैटर्न से मेल खाता है foo? हां, इसलिए हालत मेल खाती है।
      • इस स्थिति से जुड़ी कोई कार्रवाई नहीं है, इसलिए डिफ़ॉल्ट कार्रवाई करें, जिसे पथ प्रिंट करना है।
    • क्या मार्ग एक निर्देशिका है? हां, तो इसे पीछे छोड़ दें। प्रविष्टियों में /tmp/fooप्रवेश करें, और प्रत्येक प्रविष्टि के लिए, ट्रैवर्सल प्रक्रिया करें।
      • निर्देशिका खाली है: इसमें इसके अलावा कोई प्रविष्टि नहीं है .और .., जो findपुनरावृत्ति नहीं करता है। तो काम ख़त्म।

ऐसा होता है कि .और /tmp/fooएक ही निर्देशिका हैं, लेकिन यह गारंटी देने के लिए पर्याप्त नहीं है कि findदोनों पर समान व्यवहार है। findआदेश एक ही फाइल को रास्तों के बीच भेद करने के लिए तरीके हैं; -nameविधेय उनमें से एक है। find /tmp/foo -name fooशुरुआती निर्देशिका के साथ-साथ किसी भी फ़ाइल के नीचे मेल खाता है जिसे यह कहा जाता है foofind . -name .केवल शुरुआती निर्देशिका से मेल खाता है ( .एक पुनरावर्ती ट्रावेल के दौरान कभी नहीं पाया जा सकता है)।


"इसके अलावा और कोई प्रविष्टि नहीं है। और .., जो पाता है कि पुनरावृत्ति नहीं करता है।" मेरा मानना ​​है कि "पुनरावृत्ति नहीं करता है" का संदर्भ ".."। अगर यह सही है, तो ".." के संदर्भ में "अनुप्रस्थ रूप से" का क्या अर्थ होगा?
फहीम मीठा

@FaheemMitha "पुनरावृत्ति नहीं करता है" दोनों पर लागू होता है .और ..। (यदि पुनरावर्ती रूप से findट्रेस किया गया है ., तो यह निर्देशिका के माध्यम से फिर से और फिर से और फिर से समाप्त हो जाएगा ...) .और ..केवल विशेष अंकन नहीं हैं, वे निर्देशिका प्रविष्टियों के रूप में दिखाई देते हैं।
गिल्स एसओ- बुराई को रोकना '

5

परीक्षण लागू होने से पहले कमांड लाइन के तर्क का कोई सामान्यीकरण नहीं है। इस प्रकार उपयोग किए गए पथ के आधार पर परिणाम भिन्न होते हैं (यदि सीमलिंक शामिल हैं):

cd /tmp
mkdir foo
ln -s foo bar
find /tmp/foo -name foo
find /tmp/bar -name foo

"आपका मामला" में दोनों कॉल एक ही परिणाम देगा जो (अधिक) भ्रामक हो सकता है। -mindepth 1यदि आप आरंभिक बिंदुओं को अनदेखा कर सकते हैं (आप गैर-पॉसिक्स हो सकते हैं) का उपयोग कर सकते हैं ।


-mindepth 1काम करता है। हालाँकि, मुझे अभी भी समझ में नहीं आया कि अलग व्यवहार क्यों find . -name 'foo'और कैसे किया जाए find /tmp/foo -name 'foo'
यॉर्क

2

(गन्नू) कमांड के लिए दिए गए मार्ग के भीतर पाए गए किसी भी मैच को दिखाता है क्योंकि यह कमांडलाइन तर्कों के साथ अपनी तुलना शुरू करता है, वहां से निर्देशिका संरचना में गहराई से उतरता है (इस प्रकार, -maxdepth 0परीक्षण को आधार स्तर या कमांडलाइन तर्कों तक सीमित करता है, जबकि -mindepth 1के रूप में कमांडलाइन तर्कों को man findदर्शाता है)। यही कारण है कि find /tmp/foo -name 'foo'निर्देशिका के खाली होने पर भी एक ही मैच होगा।

find . -name 'foo'दूसरी ओर कोई परिणाम नहीं निकलेगा क्योंकि .(डॉट) एक विशेष फ़ाइल है जो हार्ड इनलाइन की तरह ही इनोड में काम करती है /tmp/foo- यह एक अलग (हालांकि विशेष) फ़ाइलनाम की तरह है और प्रतीकात्मक लिंक या एक अभिव्यक्ति के अधीन नहीं है खोल द्वारा pathname विस्तार। इसलिए, दिए गए उदाहरण में कमांडलाइन तर्कों को खोजने के लिए लागू पहला परीक्षण कोई मैच नहीं दिखाएगा, क्योंकि .वास्तव में परिभाषित नाम पैटर्न से मेल नहीं खाता है -name 'foo'। न तो /tmp/foo/.किसी -nameपैटर्न के लिए एक परीक्षण केवल पथ के बेसन पर किया जाता है (देखें man find), जो यहां फिर से है .

हालांकि यह व्यवहार अपेक्षित नहीं हो सकता है या उपयोगकर्ता के दृष्टिकोण से सहज नहीं हो सकता है (और हां, यह मुझे पहले भी उलझन में था), यह एक बग का गठन नहीं करता है, लेकिन आदमी में वर्णित तर्क और कार्यक्षमता के साथ मेल खाता है और (के लिए) gnu) पाते हैं।


0

मैंने गाइल्स के उत्तर पर टिप्पणी करने की कोशिश की है, लेकिन यह एक टिप्पणी में फिट होने के लिए बहुत लंबा था। इस कारण से, मैं इसे अपने प्रश्न के उत्तर के रूप में डाल रहा हूं।

गाइल्स का स्पष्टीकरण (और शेक के रूप में अच्छी तरह से) स्पष्ट है और समझ में आता है। यहां मुख्य बात यह है कि न केवल findदिए गए रास्तों (पुनरावर्ती) के अंदर की फाइलों के लिए फाइल के नामों का मिलान करने की कोशिश करता है , बल्कि यह दिए गए रास्तों के आधार नाम से भी मेल खाने की कोशिश करता है।

दूसरी ओर, क्या इसका कोई प्रमाण है कि यह तरीका findबग के बजाय काम करने का है? मेरी राय में, यह बेहतर होगा यदि यह परिणामों के लिए असंगत नहीं बनाता है find .और find ABSOLUTE-PATHक्योंकि असंगतता हमेशा भ्रामक है और डेवलपर को बहुत समय बर्बाद कर सकता है जो "क्या गलत था" यह पता लगाने की कोशिश कर रहा है। मेरे मामले में, मैं एक स्क्रिप्ट लिख रहा था, और रास्ता एक चर से लिया गया था। इसलिए मेरी स्क्रिप्ट को ठीक से काम करने के लिए, जो मैं करने के लिए सोच सकता हूं वह लिखना है find $path/. -name 'pattern'

अंत में, मुझे लगता है कि आगे बढ़ने से पहले वर्तमान निर्देशिका findके .साथ प्रतिस्थापन करके हमेशा के लिए लगातार परिणाम प्राप्त किया जा सकता है ।


-1

fooउस निर्देशिका में नामित कोई ऑब्जेक्ट नहीं है जहां आपने सापेक्ष खोज शुरू की है।

आप यह मानते हुए सही हैं कि जब एक प्रारंभिक निर्देशिका के रूप में निरपेक्ष नाम का उपयोग करते gfindसमय यह बगिया होता है /tmp/foo

Gfindमानक से विभिन्न विचलन हैं, ऐसा लगता है कि आपने एक और पाया। जब आप अधिक मानक अनुपालन समाधान पसंद करते हैं, तो मैं सुझाव देता हूं sfindकि इसका हिस्सा है schilytools

-nameनिर्देशिका खोज परिणामों पर लागू होता है। आपके द्वारा उल्लिखित दो मामलों में fooसे कोई भी एक readdir()ऑपरेशन से निर्देशिका प्रविष्टि नहीं लौटाएगा ।


मुझे शक है कि यह एक बग भी है। यहाँ से आउटपुट है find --version: find (GNU findutils) 4.4.2 Copyright (C) 2007 Free Software Foundation, Inc. लाइसेंस GPLv3 +: GNU GPL संस्करण 3 या बाद में < gnu.org/licenses/gpl.html >
York

ठीक है, मैंने आपके उदाहरण कमांड find(POSIX प्रमाणित), gfindऔर sfind; समस्या केवल तब होती है जब आप उपयोग करते हैं gfind। लिनक्स पर, gfindयह मूल नाम के तहत नहीं बल्कि नाम के तहत स्थापित किया गया है find
शास्त्री

3
यह find /tmp/foo -name fooआउटपुट के लिए सही है /tmp/foo। (Cc @York) यह OpenBSD find, GNU find, बिजीबॉक्स find, सोलारिस find, और किसी भी अन्य POSIX- अनुरूप का व्यवहार है find("प्राथमिक सच के रूप में मूल्यांकन करेगा यदि फ़ाइलनाम के आधार का परीक्षण किया जा रहा है पैटर्न (…)" - जब फ़ाइलनाम एक पथ संचालक के रूप में पारित किया गया है, कोई readdirकॉल शामिल नहीं है)।
गाइल्स का SO- बुराई से दूर रहना '
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.