शेल स्क्रिप्ट में निर्देशिका में फ़ाइलों की सूची कैसे प्राप्त करें?


159

मैं शेल स्क्रिप्ट का उपयोग करके निर्देशिका की सामग्री प्राप्त करने की कोशिश कर रहा हूं।

मेरी स्क्रिप्ट है:

for entry in `ls $search_dir`; do
    echo $entry
done

$search_dirएक सापेक्ष मार्ग कहाँ है। हालांकि, $search_dirउनके नाम में व्हॉट्सएप के साथ कई फाइलें हैं। उस स्थिति में, यह स्क्रिप्ट अपेक्षित रूप से नहीं चलती है।

मुझे पता है कि मैं उपयोग कर सकता हूं for entry in *, लेकिन यह केवल मेरी वर्तमान निर्देशिका के लिए काम करेगा।

मुझे पता है कि मैं उस निर्देशिका को बदल सकता हूं, उपयोग कर सकता हूं for entry in *फिर वापस बदल सकता हूं, लेकिन मेरी विशेष स्थिति मुझे ऐसा करने से रोकती है।

मैं दो संबंधित पथ है $search_dirऔर $work_dir, और मैं दोनों पर काम करने के लिए एक साथ है, पढ़ने के लिए उन्हें बनाने / आदि उन में फ़ाइलों को हटाने

तो अब मैं क्या करूं?

PS: मैं बैश का उपयोग करता हूं।

जवाबों:


274
for entry in "$search_dir"/*
do
  echo "$entry"
done

4
क्या आप बता सकते हैं कि for entry in "$search_dir/*"काम क्यों नहीं करते? हमें /*उद्धरणों से बाहर जाने की आवश्यकता क्यों है ?
मर्ग्लूम

6
@mrloloom: क्योंकि आपको शेल वाइल्डकार्ड को खोलना होगा।
इग्नासियो वाज़क्वेज़-अब्राम्स

findतेज नहीं होगा?
Alexej मगुरा

4
समाधान पूरा रास्ता देता है। क्या होगा यदि मैं केवल यह जानना चाहता हूं कि वर्तमान निर्देशिका में क्या था?
ThatsRightJack

1
@mrgloom आप के साथ है कि प्राप्त कर सकते हैं करना चाहते हैंfor entry in "${search_dir}/*"
funilrys

28

यहाँ पर अन्य उत्तर बहुत अच्छे हैं और आपके प्रश्न का उत्तर देते हैं, लेकिन "निर्देशिका में फ़ाइलों की सूची प्राप्त करें" के लिए यह शीर्ष Google परिणाम है, (जो मैं फ़ाइलों की सूची को बचाने के लिए देख रहा था) तो मैंने सोचा कि मैं पोस्ट करूँगा उस समस्या का जवाब:

ls $search_path > filename.txt

यदि आप केवल एक निश्चित प्रकार चाहते हैं (जैसे कोई .txt फाइलें):

ls $search_path | grep *.txt > filename.txt

ध्यान दें कि $ search_path वैकल्पिक है; ls> filename.txt करंट डायरेक्टरी करेगा।


केवल .txt फ़ाइलों को प्राप्त करने के लिए grep का उपयोग करने की आवश्यकता नहीं है: `ls $ search_path / *। Txt> filename.txt '। लेकिन इससे भी महत्वपूर्ण बात यह है कि किसी को फ़ाइल नामों को पार्स करने के लिए ls कमांड के आउटपुट का उपयोग नहीं करना चाहिए।
विक्टर ज़मानियन

1
@VictorZamanian, क्या आप विस्तार से बता सकते हैं कि हमें lsपार्स फिल्नाम के उत्पादन का उपयोग क्यों नहीं करना चाहिए ? इससे पहले इसके बारे में नहीं सुना।
समुराई_जाने 16

1
@samurai_jane इस विषय के बारे में बताने के लिए बहुत सारे लिंक हैं, लेकिन यहां एक पहला खोज परिणाम है: mywiki.wooledge.org/ParsingLs । मैंने एसओ पर एक प्रश्न भी देखा था जिसमें दावा किया गया था कि एलएस के उत्पादन को पार्स न करने के कारण बीएस थे और इसके बारे में बहुत विस्तृत था। लेकिन जवाब / जवाब अभी भी दावा किया कि यह एक बुरा विचार था। एक नज़र है: unix.stackexchange.com/questions/128985/…
विक्टर

26

यह ऐसा करने का एक तरीका है जहाँ वाक्य रचना मेरे लिए समझने में सरल है:

yourfilenames=`ls ./*.txt`
for eachfile in $yourfilenames
do
   echo $eachfile
done

./वर्तमान कार्यशील निर्देशिका है, लेकिन इसे किसी भी पथ
*.txtरिटर्न के साथ प्रतिस्थापित किया जा सकता है। कुछ भी
आप यह जांच सकते हैं कि टाइप करके आसानी से क्या सूचीबद्ध किया जाएगाls टर्मिनल में सीधे कमांड ।

मूल रूप से, आप एक चर बनाते हैं yourfilenamesजिसमें सब कुछ सूची कमांड एक अलग तत्व के रूप में देता है, और फिर आप इसके माध्यम से लूप करते हैं। लूप एक अस्थायी चर बनाता eachfileहै जिसमें चर का एक तत्व होता है जिसके माध्यम से लूपिंग होता है, इस मामले में एक फ़ाइल नाम। यह आवश्यक रूप से अन्य उत्तरों से बेहतर नहीं है, लेकिन मुझे यह सहज लगता है क्योंकि मैं पहले से ही lsकमांड और लूप सिंटैक्स के लिए परिचित हूं ।


यह एक त्वरित, अनौपचारिक स्क्रिप्ट या वन-लाइनर के लिए ठीक काम करता है, लेकिन यह टूट जाएगा अगर फ़ाइल नाम में ग्लोब-आधारित समाधानों के विपरीत, नई सुर्खियाँ हों।
सोरेन ब्योर्नस्टैड

@SorenBjornstad सलाह के लिए धन्यवाद! मुझे नहीं पता था कि फ़ाइल नाम में नई सूचियों को अनुमति दी गई थी- उनमें किस प्रकार की फाइलें हो सकती हैं? जैसे, क्या यह कुछ ऐसा है जो आमतौर पर होता है?
rrr

फ़ाइलनामों में न्यूलाइन्स इस कारण से खराब हैं और जहाँ तक मुझे पता है कि उनका उपयोग करने का कोई वैध कारण नहीं है। मैंने कभी खुद को जंगल में नहीं देखा। उस ने कहा, यह पूरी तरह से संभव है कि इस तरह से शोषण करने के लिए नए नाम के साथ फाइलनेम का निर्माण किया जाए। (उदाहरण के लिए, फ़ाइलों से युक्त निर्देशिका की कल्पना करें A, Bऔर C। आप नामक फ़ाइलें बनाते हैं B\nCऔर Dफिर उन्हें हटाने के लिए चुनते हैं। इस अधिकार को संभालने वाले सॉफ़्टवेयर को आपके पास नहीं होने पर भी, बजाय Preexisting फ़ाइलों को हटाने की समाप्ति हो सकती है। ऐसा करने की अनुमति।)
सोरेन ब्योर्नस्टैड


11
find "${search_dir}" "${work_dir}" -mindepth 1 -maxdepth 1 -type f -print0 | xargs -0 -I {} echo "{}"

1
मुझे पता है कि यह बहुत पुराना है, लेकिन मुझे अंतिम xargs -0 -i echo "{}"आदेश नहीं मिल सकता है , मुझे थोड़ा समझाने की परवाह है? विशेष रूप से -i echo "{}"भाग क्या है? इसके अलावा, मैं उस manपृष्ठ से पढ़ता हूं जो -iअब पदावनत है और हमें -Iinsted का उपयोग करना चाहिए ।
drkg4b

1
-iअर्ग के {}साथ स्थानापन्न ।
नोएल याप

धन्यवाद! यह मेरे जैसे धीमे दिमाग के लिए भी उपयोगी है, मुझे लगता है कि {}वह स्ट्रिंग है जिसे findकमांड द्वारा मैचों के साथ बदल दिया जाता है ।
drkg4b

3
आप उपयोग क्यों करते हैं xargs? डिफ़ॉल्ट रूप से, findप्रिंट करता है कि यह क्या पाता है ... आप सब कुछ हटा सकते हैं -print0
gniourf_gniourf

1
ऐसा करने से रिक्त स्थान के साथ फ़ाइल प्रविष्टियों को संभाल नहीं पाएंगे।
नोएल याप

4
$ pwd; ls -l
/home/victoria/test
total 12
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  a
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  b
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  c
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:32 'c d'
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  d
drwxr-xr-x 2 victoria victoria 4096 Apr 23 11:32  dir_a
drwxr-xr-x 2 victoria victoria 4096 Apr 23 11:32  dir_b
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:32 'e; f'

$ find . -type f
./c
./b
./a
./d
./c d
./e; f

$ find . -type f | sed 's/^\.\///g' | sort
a
b
c
c d
d
e; f

$ find . -type f | sed 's/^\.\///g' | sort > tmp

$ cat tmp
a
b
c
c d
d
e; f

बदलाव

$ pwd
/home/victoria

$ find $(pwd) -maxdepth 1 -type f -not -path '*/\.*' | sort
/home/victoria/new
/home/victoria/new1
/home/victoria/new2
/home/victoria/new3
/home/victoria/new3.md
/home/victoria/new.md
/home/victoria/package.json
/home/victoria/Untitled Document 1
/home/victoria/Untitled Document 2

$ find . -maxdepth 1 -type f -not -path '*/\.*' | sed 's/^\.\///g' | sort
new
new1
new2
new3
new3.md
new.md
package.json
Untitled Document 1
Untitled Document 2

टिप्पणियाँ:

  • . : मौजूदा फोल्डर
  • -maxdepth 1पुनरावर्ती खोजने के लिए निकालें
  • -type f: फ़ाइलें खोजें, निर्देशिका नहीं ( d)
  • -not -path '*/\.*' : नहीं लौटा .hidden_files
  • sed 's/^\.\///g': ./परिणाम सूची में से निकाला गया हटा दें

0

यहां निर्देशिका के अंदर फ़ाइलों को सूचीबद्ध करने का एक और तरीका है (एक अलग उपकरण का उपयोग करना, कुछ अन्य उत्तरों की तरह कुशल नहीं)।

cd "search_dir"
for [ z in `echo *` ]; do
    echo "$z"
done

echo *वर्तमान निर्देशिका की सभी फाइलों को आउटपुट करता है। forपाश stdout के लिए प्रत्येक फ़ाइल नाम और प्रिंट से अधिक iterates।

इसके अतिरिक्त, यदि निर्देशिका के अंदर निर्देशिका की तलाश है तो इसे forलूप के अंदर रखें :

if [ test -d $z ]; then
    echo "$z is a directory"
fi

test -d जाँचता है कि फ़ाइल एक निर्देशिका है या नहीं।


0

स्वीकृत उत्तर फाइलों को उपसर्ग के साथ वापस नहीं करेगा। उस उपयोग को करने के लिए

for entry in "$search_dir"/* "$search_dir"/.[!.]* "$search_dir"/..?*
do
  echo "$entry"
done

-1

लिनक्स वर्जन पर मैं निम्नलिखित कार्यों के साथ (x86_64 GNU / लिनक्स) काम करता हूं:

for entry in "$search_dir"/*
do
  echo "$entry"
done

-1: यह स्वीकृत उत्तर के समान है सिवाय इसके कि यह चर को उद्धृत नहीं करता है। उद्धृत न करने का $search_dirअर्थ है कि यदि निर्देशिका नाम में कोई स्थान है तो वह टूट जाता है। (इस मामले में आप उद्धृत न करने के साथ दूर हो सकते हैं $entry, लेकिन इसे उद्धृत करने के लिए बेहतर अभ्यास होगा।)
सोरेन ब्योर्नस्टैड

तुम गलत हो। मेरा समाधान समान नहीं है, भले ही वह स्वीकृत उत्तर के समान हो। और यह गलत नहीं है, यह काम करता है। यहाँ मैंने मैक ओएस सहित विभिन्न यूनिक्स प्रणालियों पर कोशिश की है, और यह उनमें से हर एक पर काम करता है। रिक्त के साथ फ़ाइल, यहां तक ​​कि जब इसमें नाम के प्रमुख रिक्त स्थान होते हैं, तो ठीक से प्रदर्शित किया जाता है। search_dir =। $ search_dir / * में प्रवेश के लिए; $ गूंज करो; किया गया ।/ आ आआ। txt ।/add ।/apm_tables.txt आप समाधान पर वोट दे सकते हैं जब आप यह साबित कर सकते हैं कि समाधान काम नहीं करता है या गलत परिणाम उत्पन्न करता है।
आंद्रशेंको अलेक्जेंडर

यदि आप मेरी टिप्पणी को थोड़ा और करीब से पढ़ते हैं, तो आप देखेंगे कि समस्या निर्देशिका नाम में रिक्त है , न कि फ़ाइल नाम। यह प्रश्नकर्ता के भाग जाने के मुद्दे से अलग है, लेकिन इसका मतलब यह है कि कोड अनायास ही टूट सकता है! यहाँ एक उदाहरण है जो काम नहीं करता है mkdir "x y"; touch "x y/1.txt"; search_dir="x y"; for entry in $search_dir/*; do echo $entry; done:। लूप दो बार चलता है, एक बार मुद्रण xऔर दूसरी बार y/*, जो संभवतः अपेक्षित परिणाम नहीं है।
सोरेन ब्योर्नस्टैड

और मैं अनुचित रूप से गलत तरीके से समझे गए चर को गलत मानता हूं, जो कि गिरावट का आधार है। फ़ाइलों को छोड़ते समय खोज निर्देशिका के किसी भी उपनिर्देशिका को हटाने के लिए इस कोड पर विचार करें search_dir="x y"; for entry in $search_dir/*; do if [ -d "$entry" ]; then rm -rf "$entry"; fi; done:। यदि xवर्तमान निर्देशिका में एक निर्देशिका भी है , तो यह संक्षेप में हटा दिया गया है, सिर्फ इसलिए कि आपने अपने चर को उद्धृत नहीं किया है!
सोरेन ब्योर्नस्टैड

खैर, आप हमेशा एक कार्य के लिए बनाया गया कोड लेते हैं, कार्य को थोड़ा बदल देते हैं और कोड गलत हो जाता है। मेरे प्रस्तावित समाधान कार्यों के लिए पूछे गए प्रश्न के लिए। लेकिन ... एक डेवलपर होने के नाते मुझे आपके तर्कों से सहमत होना होगा: वेन हम एक कोड को अधिक मजबूत और सामान्य बना सकते हैं, हमें यह करना चाहिए। तो मैं qoutes जोड़ दूंगा। यह मेरे उत्तर को ऊपर दिए गए उत्तर के समान बना देगा, लेकिन डिस्क्यूशन के लिए (जो किसी के लिए उपयोगी हो सकता है) मैं उत्तर को भी छोड़ देता हूं।
एंड्रुशेंको अलेक्जेंडर

-1

बस यह सरल कमांड दर्ज करें:

ls -d */

क्या आप कुछ स्पष्टीकरण प्रदान कर सकते हैं @ मिचेल सिस्को
विपुल

ls (सूची) -d (सूची केवल निर्देशिका) * / (किसी भी पैटर्न की, बैकस्लैश सूची को केवल निर्देशिका में प्रतिबंधित करता है)।
माइकल सिस्को
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.