मैं `खोज` का उपयोग करके एक चौड़ाई-पहली खोज कैसे कर सकता हूं?


17

-depthकरने के लिए प्राथमिक findयह गहराई-प्रथम खोज करने के लिए कारण बनता है।

हालांकि, डिफ़ॉल्ट अनुक्रम है नहीं एक चौड़ाई-पहले खोज।

डिफ़ॉल्ट अनुक्रम को अनौपचारिक रूप से "गहराई-पहला ट्रैवर्सल" के रूप में वर्णित किया जा सकता है जो नोड्स को संभालता है जब वे बैकट्रैकिंग के दौरान ऐसा करने के बजाय पहली बार सामना करते हैं । "

मुझे पहले खोज के लिए चौड़ाई की वास्तविक आवश्यकता है। मैं findइस तरह से कैसे व्यवहार कर सकता हूं ?


उदाहरण के लिए, निम्नलिखित सेटअप के साथ:

$ mkdir -p alpha/{bravo,charlie,delta}
$ touch alpha/charlie/{alpha,beta,gamma,phi}

find निम्नलिखित डिफ़ॉल्ट व्यवहार है:

$ find alpha
alpha
alpha/charlie
alpha/charlie/alpha
alpha/charlie/phi
alpha/charlie/beta
alpha/charlie/gamma
alpha/delta
alpha/bravo

और -depth, यह निम्नानुसार प्रदर्शन करता है:

$ find alpha -depth
alpha/charlie/alpha
alpha/charlie/phi
alpha/charlie/beta
alpha/charlie/gamma
alpha/charlie
alpha/delta
alpha/bravo
alpha

हालाँकि, जो मैं चाहता हूं वह निम्नलिखित (काल्पनिक) विकल्प है:

$ find alpha -bfs
alpha
alpha/charlie
alpha/delta
alpha/bravo
alpha/charlie/alpha
alpha/charlie/phi
alpha/charlie/beta
alpha/charlie/gamma

दूसरे शब्दों में, मुझे आगे बढ़ने से पहले सभी फाइलों / डायरियों पर एक निश्चित गहराई findपर प्रक्रिया / रिपोर्ट करने की आवश्यकता है ।

मैं यह कैसे कर सकता हूँ?


साथ नहीं find(कम से कम, केवल साथ नहीं find)। क्या आप केवल फाइलों को सूचीबद्ध करना चाहते हैं, या क्या आप अन्य प्राइमरी का उपयोग करना चाहते हैं?
गिल्स एसओ- बुराई को रोकें '

@ गिल्स, वास्तव में मुझे एहसास हुआ कि मुझे जो -bfsचाहिए वह काफी नहीं होगा ... मेरे पास एक सरल स्क्रिप्ट है जो एक बड़ी GitLab परियोजना के लिए एक सूचकांक उत्पन्न करती है, जो GitLab Wiki में शामिल करने के लिए उपयुक्त है। यह निर्देशिका नामों के आधार पर हेडर को पदानुक्रमित बनाता है। यह बहुत अच्छा काम करता है, सिवाय इसके कि उदाहरण फ़ाइल संरचना में यह उपर्युक्त के तहत, अभिभावक शीर्षलेख के बजाय उप-धारक के deltaनीचे रखा जाएगा । charliealpha
वाइल्डकार्ड

एक और विचित्र बात यह है कि मेरा findआउटपुट वर्णानुक्रम में क्रमबद्ध है। पता नहीं क्यों ....
वाइल्डकार्ड

फिर भी, मुझे लगता है कि -bfs यह काम में आ सकता है , भले ही यह इस उपयोग के मामले में पूरी तरह फिट न हो।
वाइल्डकार्ड

2
मैंने ऐसा उपकरण लागू किया: bfs । यह जीएनयू खोजने में अभी तक 100% फ़ीचर-संगत नहीं है, लेकिन यह वहां हो रहा है।
तेवियन बार्न्स

जवाबों:


6

आप इसे केवल शेल वाइल्डकार्ड के साथ कर सकते हैं। उत्तरोत्तर अधिक निर्देशिका स्तरों के साथ एक पैटर्न बनाएँ।

pattern='*'
set -- $pattern
while [ $# -ne 1 ] || [ "$1" != "$pattern" ]; do
  for file; do
    …
  done
  pattern="$pattern/*"
  set -- $pattern
done

इससे डॉट फाइलें याद आती हैं। का प्रयोग करें FIGNORE='.?(.)'ksh में, shopt -s dotglobपार्टी में, या setopt glob_dotszsh में उन्हें शामिल करने के लिए।

चेतावनियां:

  • यदि बहुत सारी फाइलें हैं तो यह मेमोरी को उड़ा देगा।
  • यह पुनरावर्ती निर्देशिकाओं के प्रतीकात्मक लिंक का पता लगाता है।

यदि आप ऑर्डर या निर्देशिका और गैर-निर्देशिका चुनना चाहते हैं, और प्रदर्शन महत्वपूर्ण नहीं है, तो आप [ -d "$file" ]प्रत्येक पास पर दो पास और परीक्षण कर सकते हैं ।


@Wildcard हाँ, मैंने किया था।
गिल्स एसओ- बुराई को रोकना '

1
अच्छा! एक और लगभग तुच्छ कैविएट: यह एक फ़ाइल को संसाधित करने में विफल हो जाएगा जो एक निर्देशिका में अकेली फ़ाइल है यदि फ़ाइल का शाब्दिक नाम है *। :)
वाइल्डकार्ड

@Wildcard ओह, हाँ, मैं यह उल्लेख करना भूल गया। इस किनारे के मामले से बचने के लिए बैश या zsh का उपयोग करें nullglobऔर (($#))लूप स्थिति के रूप में उपयोग करें ।
गिल्स एसओ- बुराई को रोकना '

5

# cat ./bfind

#!/bin/bash
i=0
while results=$(find "$@" -mindepth $i -maxdepth $i) && [[ -n $results ]]; do
  echo "$results"
  ((i++))
done

यह findऔर गहराई को दोहराते हुए काम करता है , मुझे लगता है कि यह परिणाम दोहरा सकता है, लेकिन आसानी से फ़िल्टर किया जा सकता है


क्षमा करें, मुझे प्रारूपण तंत्र के बारे में नहीं पता था। वैसे भी, वास्तव में यह मुझे नहीं लगता है क्योंकि मुझे लगता है कि यह किसी भी चीज़ को दिमाग से कम करता है
user239175

3

आप अपने findप्रकार को मुख्य रूप से /पथनाम में वर्णों की संख्या के आधार पर छाँट सकते हैं। उदाहरण के लिए,

find alpha |
awk '{n=gsub("/","/",$0);printf "%04d/%s\n",n,$0}' |
sort -t/ |
sed 's|[^/]*/||'

यह awkस्लैश की संख्या के साथ pathname को उपसर्ग sedकरने के लिए और अंत में इस उपसर्ग को हटाने के लिए उपयोग करता है ।

दरअसल, जैसा कि आप चाहते हैं कि निर्देशिका की सामग्री को alpha/charlie+बाद में सूचीबद्ध किया जाए alpha/charlie, आपको sort -t/ -k1,1 -k2,2 -k3,3 -k4,4वांछित गहराई तक कहने की आवश्यकता है।


0

एक अन्य उत्तर 'खोज' पर आधारित नहीं है, लेकिन बैश पर - पहले "मूल निर्देशिका की लंबाई" का उपयोग करें, फिर अल्फा के आधार पर छाँटें।

जवाब काफी मेल नहीं खाता है क्योंकि आपके परिणामों में "चार्ली, ब्रावो, डेल्टा" है, लेकिन मुझे आश्चर्य है कि क्या यह अल्फा क्रम में "ब्रावो, चार्ली, डेल्टा" होना चाहिए।

paths_breadth_first() {
  while IFS= read -r line; do
    dirn=${line%/*}         ## dirname(line)
    echo ${#dirn},$line     ## len(dirn),line
  done | sort -n | cut -d ',' -f 2-
}

वह पैदा करता है

  $ cat /tmp/yy | paths_breadth_first 
  alpha
  alpha/bravo
  alpha/charlie
  alpha/delta
  alpha/charlie/alpha
  alpha/charlie/beta
  alpha/charlie/gamma
  alpha/charlie/phi
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.