फ़ाइल नामों को सूचीबद्ध करने के लिए कमांड का उपयोग कैसे करें लेकिन पथ नहीं?

Jan 06 2021

मैंने ऑनलाइन कुछ उत्तरों की जाँच की है, लेकिन वे तब काम नहीं करते हैं जब -nameकमांड में कोई पैरामीटर हो (हो सकता है कि मैं कुछ गलत कर रहा हूँ, निश्चित नहीं)। मैं जो करना चाहता हूं वह केवल फ़ाइल नाम (निर्देशिका / पथ नहीं) सूचीबद्ध करने के लिए है, और अधिक जटिल करने के लिए, मेरे पास अलग-अलग एक्सटेंशन के साथ एक ही फ़ाइल नाम है, इसलिए मुझे परिणाम का उपयोग करके फ़िल्टर करने की आवश्यकता है -nameऔर -o, परेशानी यह है कि सुझाव -printfया तो उपयोग देखा या basename, और जब वहाँ अच्छी तरह से काम नहीं करता है -name *.txt -o name *.pdf। क्या इस समस्या को हल करने का कोई और तरीका है?

मेरी फ़ाइलों का उदाहरण:

/dir1/dir2/dir3/dir4/
                    /file1.txt
                    /file1.pdf
                    /file1.ods ...etc.

मैं केवल प्रति सूची एक या अधिक प्रकार की फ़ाइल सूचीबद्ध करने में दिलचस्पी रखता हूं ( -nameमेरे परिणामों को फ़िल्टर करने के लिए उपयोग करके)

क्या इसे केवल 1 findकमांड का उपयोग करके पूरा करना संभव है या मुझे इसे 2 चरणों में करना होगा (परिणाम को अस्थायी फ़ाइल में सहेजना है, फिर निर्देशिका को अस्थायी फ़ाइल से फ़िल्टर / पट्टी करना)? परिणाम मैं पूरा करने की कोशिश कर रहा हूँ प्रति पंक्ति फ़ाइल नाम के साथ एक पाठ फ़ाइल है:

file1.txt
file1.pdf
file1.ods
file2.txt
file2.pdf
etc.

मैं जिस कमांड का उपयोग कर रहा था वह है

find /dir1/dir2/dir3/dir4/ -type f -name '*.txt' -o -name '*.pdf' -o -name '*.ods' -printf "%f\n"

मैं ग्नू खोज का उपयोग कर रहा हूं।

अपडेट करें

यह निकला कि मुझे \(...\)αнsнι to द्वारा याद दिलाना है

जवाब

3 αғsнιη Jan 06 2021 at 21:02

जब -oआपके साथ तार्किक या मोड में कई अभिव्यक्तियों का उपयोग किया जाता है \( ... \), तो उन्हें उन सभी को संलग्न करने की आवश्यकता होती है , अन्यथा अंतिम अभिव्यक्ति परिणाम हमेशा सम्मानित होता है; और -printf '%f\n'फ़ाइलों का नाम केवल किसी भी प्रमुख निर्देशिका को हटाने के साथ मुद्रित करने के लिए उपयोग किया जाता है।

find . -type f \( -name '*.pdf' -o -name '*.txt' \) -printf '%f\n'

OPERATORS अनुभाग के man findअंतर्गत देखें :( expr )

OPERATORS
...

(expr)
बल पूर्वता। चूंकि कोष्ठक खोल के लिए विशेष हैं, इसलिए आपको आमतौर पर उन्हें उद्धृत करने की आवश्यकता होगी।

तो आप या तो उपयोग कर सकते हैं \( ... \)या '(' ... ')'(कोष्ठक के पहले और बाद में व्हाट्सएप महत्वपूर्ण हैं) उन्हें बचने के लिए।

1 Kusalananda Jan 06 2021 at 22:58

जैसा कि पहले ही उल्लेख किया गया है, आपको अपने -nameपरीक्षणों को कोष्ठकों में समूहित करने की आवश्यकता है। इन कोष्ठकों को शेल से बचाने के लिए \( ... \)उदाहरण के रूप में भाग जाने या उद्धृत करने की आवश्यकता होती है '(' ... ')'(जहां वे अन्यथा एक उपसमुच्चय को नामित करेंगे)।

मानक का उपयोग करना find, और फ़ाइल नाम प्रत्ययों को संभालना भी थोड़ा आसान है:

set -- txt pdf ods

for suffix do
    set -- "$@" -o -name "*.$suffix"
    shift
done
shift

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec basename {} \;

यह पहले फ़ाइल नाम प्रत्यय की सूची में स्थितीय मापदंडों को निर्धारित करता है जिसे हम देखना चाहते हैं (इसे कमांड लाइन से भी लिया जा सकता है यदि यह एक स्क्रिप्ट है), और -nameपरीक्षण की OR- सूची का निर्माण करता है । यह तब findकमांड लाइन में उपयोग किया जाता है ।

findआदेश में ही तो कहता है basenameप्रत्येक मिली नाम के लिए उपयोगिता।

एक विकल्प के रूप में, हम इसके बजाय सभी pathname के फ़ाइल नाम घटक को हटाने के लिए एक पैरामीटर प्रतिस्थापन का उपयोग कर सकते हैं, लेकिन ऐसा करने के लिए हमें एक इनलाइन sh -cस्क्रिप्ट में pathnames को पास करना होगा :

# [...] as before [...]

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec sh -c '
    for pathname do
        printf "%s\n" "${pathname##*/}"
    done' sh {} +

मैं उम्मीद करूंगा कि इसका उपयोग भिन्नता की तुलना में अधिक तेज होगा basename, कम से कम यदि कई फाइलनेम को संभालना है, हालांकि जीएनयू basenameसे कोर्यूटिल्स, आप उपयोग कर सकते हैं -aया --multipleपसंद कर सकते हैं :

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec basename -a {} +

यह basenameसंभव के रूप में कुछ समय के लिए कहेंगे । लेकिन फिर, अगर आपने कोरुटिल्स स्थापित किए थे, तो आपके पास जीएनयू के साथ-साथ अच्छी तरह से फाइयूटिल्स भी findहो सकते हैं, और -printf '%f\n'वही काम करने के लिए उपयोग कर सकते हैं ।