खोजें खोज में निर्देशिकाओं को छोड़ दें


14

एक खोज के साथ locateफाइल सिस्टम में पथ मिलते हैं।
अक्सर, आप एक ऐसी प्राथमिकता जानते हैं जिसे आप या तो केवल फाइलों में या केवल निर्देशिकाओं में रुचि रखते हैं।
'खोज' खोज अक्सर कई परिणाम देता है। परिणाम में केवल एक प्रकार को शामिल करना उपयोगी होगा, क्योंकि यह आउटपुट को छोटा करने में मदद करता है।

लेकिन फ़ाइलों या निर्देशिकाओं को छोड़ने का एक और दिलचस्प तर्क है: क्योंकि परिणाम पथों की सूची अस्पष्ट हो सकती है - न केवल सिद्धांत में।

नीचे दिया गया उदाहरण वास्तविक दुनिया का मामला है, और असामान्य नहीं है:

$ locate --regex --basename "xfce4-keyboard-overlay$"
/usr/local/bin/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay

ठीक है, हमें कुछ मिला! लेकिन ... फाइलें, या निर्देशिका?

$ file /usr/local/bin/xfce4-keyboard-overlay 
/usr/local/bin/xfce4-keyboard-overlay:   bash script

तो यह एक फ़ाइल है ...

$ file /usr/local/share/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay: directory

जबकि दूसरा नहीं है।

इस अस्पष्टता को पढ़ने के लिए कठिन रास्तों की लंबी सूची बना रही है, इसलिए निर्देशिकाओं को फ़िल्टर करना वास्तव में अच्छा होगा, उदाहरण के लिए कॉमैन लाइन विकल्प का उपयोग करना locate

क्या ऐसा कुछ मौजूद है? यहां तक ​​कि अगर निर्देशिका के लिए फ़िल्टर का पता लगाने से अलग है?

कम से कम, एक स्क्रिप्ट का उपयोग करके सभी फ़ाइल नामों को जांचने के लिए उपयोग किया जा सकता है - जो धीमा हो सकता है।

जवाबों:


3

के साथ zsh:

print -rl ${(0)^"$(locate -0 ...)"}(N.)

(0)एक पैरामीटर विस्तार ध्वज है जो NUL वर्णों पर विभाजित होता है (जैसा कि हम उपयोग करते हैं locate -0), इसके लिए छोटा है (ps:\0:)

साथ ^, बजाय जोड़ने की (N.)सरणी के अंत में, हम इसे प्रत्येक तत्व में जोड़ें।

(N.)एक ग्लोब क्वालीफ़ायर है, .केवल नियमित फ़ाइलों का मिलान Nकरने के लिए, तत्व को हटाने के लिए यदि यह मेल नहीं खाता (मौजूद नहीं है या नियमित फ़ाइल नहीं है, या हम जांच नहीं कर सकते हैं)। आप केवल नियमित फ़ाइलों के बजाय गैर-निर्देशिकाओं से मिलान करने के ^/बजाय उपयोग कर सकते हैं .

print -rlप्रत्येक तर्क को एक अलग लाइन पर कच्चा छापता है ।

आप किसी भी zshग्लोब क्वालीफायर का उपयोग कर सकते हैं , लेकिन ध्यान दें कि ऑर्डर करने वालों पर कोई प्रभाव नहीं पड़ेगा, क्योंकि हम यहां प्रति फ़ाइल एक ग्लोब का विस्तार कर रहे हैं, इसलिए प्रत्येक के लिए सॉर्ट करने के लिए केवल एक फाइल है।

(ध्यान दें कि यह विफल हो सकता है यदि अंतिम फ़ाइल द्वारा रिपोर्ट की गई locateनई लाइन वर्णों में समाप्त हो जाती है (सभी शेल में मौजूद कमांड प्रतिस्थापन मिसफिट)।


3

यह अन्य उत्तरों के रूप में अयोग्य के रूप में है, लेकिन शायद कम अक्षम है:

locate --regex --basename "xfce4-keyboard-overlay$" | 
        while IFS= read -r f; do [ -f "$f" ] && printf "%s\n" "$f"; done

(पठनीयता के लिए दो लाइनों में टूट गया)। ऊपर रिक्त स्थान वाले नामों को संभालेंगे। IFS=साथ नाम को संभालने के लिए आवश्यक प्रतीत हो रहा है पीछे चल रिक्त स्थान, और, ज़ाहिर है, -rआप बैकस्लैश संभाल करने देता है।

"चलो locateकुछ में पाइप " दृष्टिकोण विफल हो सकता है अगर नए नाम वाले मार्गनाम मौजूद हैं।


अधिक जानकारी के लिए IFS, पढ़ने के लिए sh(1)या bash(1) (टाइपिंग द्वारा man shया man bashएक * nix प्रणाली में, और / या इसे पढ़ने के यहाँ , यहाँ , यहाँ , और / या यहाँ )। फिर अंडरस्टैंडिंग IFS और बैश को पढ़ें: स्टैक एक्सचेंज पर IFS के साथ लाइन द्वारा पढ़ें लाइन, (5 से अधिक वोटों के साथ उत्तरों पर ध्यान दें), और, यदि आपके पास अभी भी पर्याप्त नहीं है, तो ग्रेग के विकी और आईएफएस खोज परिणामों पर आईएफएस देखें। बैश हैकर्स विकी पर (स्टैक एक्सचेंज पर नहीं)।


क्या आप अपने whileबयान के बाद "IFS =" पर कुछ जानकारी जोड़ सकते हैं ?
रॉबर्ट रॉबर्ट


कई गूंज कार्यान्वयन के साथ बैकस्लैश अभी भी एक समस्या होगी। आपको printfमनमाने डेटा के लिए उपयोग करना चाहिए
स्टीफन चेजलस

"--null" पैरामीटर का उपयोग करके अपने न्यूलाइन्स की समस्या का समाधान हो सकता है locateऔर अपने readसुझाव के अनुसार यहां अपना नामांतर कर सकते हैं
robert

@ स्टीफनचेज़ेलस: अच्छी बात है। फिक्स्ड।
जी-मैन का कहना है कि मोनिका 'पुनः

2
locate --null --regex --basename "xfce4-keyboard-overlay$" |
  xargs -r0 sh -c 'find "$@" -prune ! -type d' sh

वास्तव में, यह जितना दिखता है उससे कहीं अधिक गंदा है ... लेकिन एक अच्छी प्रेरणा। आइए दिखाते हैं कि यह स्यूडोकोड है, फिर यह मददगार है :)
वोल्कर सेगेल

1
@ वॉलर: मैं मानता हूं कि यह बुरा है: यह आपके उदाहरण में /usr/local/share/xfce4-keyboard-overlay और प्रत्येक उपनिर्देशिका को सूचीबद्ध करेगा । जोड़ना -maxdepth 0मदद करता है।
जी-मैन का कहना है कि मोनिका '

यह और भी बेहतर हो जाता है ...: D locate --regex --basename "xfce4-keyboard-overlay$" | xargs -I % sh -c "test -d % && echo %"
FloHimself

1
के xargsसाथ उपयोग करना findएक अच्छा विचार था, मैंने इसे मजबूत बनाने के लिए इसे संपादित किया है। आशा है आप बुरा न मानें
स्टीफन चेजलस

1

xargsयदि आप निर्दिष्ट -L 1या -iपैरामीटर प्रत्येक पंक्ति के लिए कमांड दोहराएंगे ।

यहाँ देखें

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i bash -c '(test -d "{}" && echo "{}")'

बेशक, यह प्रत्येक फ़ाइल के लिए एक नए शेल की किक कर रहा है, लेकिन इसका अच्छा और कॉम्पैक्ट होने का लाभ है।

संपादित करें: मैं उस जवाब से बहुत खुश नहीं था क्योंकि यह प्रत्येक फ़ाइल के लिए एक नए शेल को किक कर रहा था। इसकी केवल दो प्रक्रियाएँ होनी चाहिए:

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i echo 'test -d "{}" && echo "{}"' | bash

निश्चित रूप से यह अच्छा होगा यदि हम एक दुभाषिया को पूरी तरह से मारने से बच सकते हैं, लेकिन xargsयह चेन कमांड्स की क्षमता में बाधा है।


3
उस एक ने मेरी मशीन को रीबूट कर दिया (एक फ़ाइल थी जिसे कहा जाता है /home/evil/$(reboot)/xfce4-keyboard-overlayऔर मैं मूर्खतापूर्ण तरीके से भाग गया root)।
स्टीफन चेजलस

2
@ StéphaneChazelas +1 को "इन्टर्नेट्स से रैंडम कोड्ज़" को रूट के रूप में चलाने की हिम्मत के लिए;) (scnr)
वोल्कर सिएगल

0

मेरे दो सेंट:

while IFS= read i; \
do \
  if [ -f "$i" ]; \
  then \
    echo "$i"; \
  fi; \
done < <(locate --regex --basename "xfce4-keyboard-overlay$")

यह कमोबेश G-Man ने जिस तरह से इसे प्रोसेस प्रतिस्थापन के साथ जोड़ा।


वास्तव में, यह कमोबेश मेरे द्वारा किए गए तरीके से है, प्रक्रिया प्रतिस्थापन के साथ संयुक्त, फ़ाइल नाम को संभालने की क्षमता है जिसमें बैकस्लैश शामिल हैं या सफेद स्थान को पीछे छोड़ते हैं। यह भी ध्यान दें कि प्रश्न शीर्षक "निर्देशिकाओं को बाहर करें" कहता है, और इस उत्तर में केवल निर्देशिकाएं शामिल हैं
जी-मैन का कहना है कि 'मोनिका'

माफ़ करना। मेरी गलती। सही किया।
ट्रिस्टन स्टॉर्च

-1

क्या होगा अगर आप के locateसाथ गठबंधन fileऔर grep? ...

$ for f in `locate --regex --basename "xfce4-keyboard-overlay$"`; do file $f; done | grep -vi directory

मैंने परीक्षण नहीं किया, लेकिन मुझे लगता है कि यह धीमा हो सकता है, क्योंकि यह fileहर एक मार्ग के लिए एक प्रक्रिया बनाता है । ध्यान दें कि पता लगाने के लिए अक्सर परिणामों की कई लाइनें होती हैं। मेरा वर्तमान परीक्षण "सूक्ति" के लिए खोज कर रहा है, परीक्षण के लिए लगभग 73000 रास्ते दे रहा है।
वोल्कर साइगेल

2
@ वॉलर: यह उससे भी बुरा है: हर $fउस फ़ाइल के लिए, fileप्रोग्राम उस फाइल को खोलेगा और उससे पढ़ेगा । यह सकल रूप से महंगा है जब आपको बस इतना करना है stat()। ………… इसके अलावा, यह उन फाइलों के लिए गलत परिणाम देगा, जिनके नाम में "निर्देशिका" होती है (जैसे कि "phone_directory")। ………… (इसके अलावा, for f in `…`; do …वाक्यविन्यास रिक्त स्थान वाले नामों को नहीं संभाल सकता है।)
G-Man Says 'Reinstate Monica'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.