मैं लिनक्स बैश में एक सरणी में ls कैसे निर्दिष्ट करूं?


87
array=${ls -d */}
echo ${array[@]}  

मेरे पास तीन निर्देशिकाएं हैं ww ee qq:। मैं उन्हें एक सरणी में चाहता हूं और फिर सरणी को प्रिंट करता हूं।


क्या इससे आपके सवाल का जवाब मिलता है? एक सरणी में फ़ाइल नाम पढ़ना
akostadinov

जवाबों:


111

यह यह होगा

array=($(ls -d */))

EDIT: अधिक सामान्य उत्तर के लिए गॉर्डन डेविसन का समाधान देखें (यानी यदि आपके फ़ाइलनाम में विशेष वर्ण हैं)। यह उत्तर केवल एक सिंटैक्स सुधार है।


14
यह सही ढंग से काम नहीं करेगा अगर निर्देशिका नामों में रिक्त स्थान हों।
शेपनर

1
रिक्त स्थान या विशेष वर्णों के मुद्दे को हल करने के लिए, पहले बिना किसी मान के ऐलान की घोषणा करें, फिर ARR+=('$(ls -d */)')किसी ऐरे में तत्वों को संपादित करने के लिए बिल्ट-इन का उपयोग करें, जबकि विशेष वर्णों से निपटने के लिए एकल एलिमेंट्स का उपयोग करते हुए, उन तत्वों को जोड़ने या हटाने के लिए। सरणी। एकल उद्धरण शाब्दिक वर्णों को संरक्षित करते हैं और निर्देशिका नामों में उनसे निपटने के लिए भागने की किसी भी आवश्यकता को हटाते हैं।
योकाई

@ योकाई आपका सुझाव अद्भुत है लेकिन मेरे लिए उबंटू 16.04 या मैकओ पर काम नहीं किया। बैश इस तरह एकल उद्धरणों के बीच कोड का विस्तार करता है: declare -a ARR; ARR+=('$(ls -d "$INPUT_DIR"/*)')केवल रिटर्न$(ls -d $INPUT_DIR/*)
एजाइल बीन

1
मेरी गलती। यह डबल उद्धरण होना चाहिए था ताकि कमांड प्रतिस्थापन का विस्तार किया जा सके। ARR+=("$(ls -d */)")कार्य करना चाहिए। अगर नहीं तो मुझे बताएं।
योकाई

2
@ योकाई, जो केवल एक तत्व को जोड़ता है (इसमें नईलाइन्स का एक गुच्छा होता है), प्रति निर्देशिका एक तत्व नहीं।
चार्ल्स डफी

79

जब भी संभव हो, आपको आउटपुट को पार्स करने से बचना चाहिए ls( विषय पर ग्रेग की विकी देखें )। असल में, lsअगर किसी भी फिल्मनाम में मज़ेदार चरित्र हैं , तो इसका उत्पादन अस्पष्ट होगा। यह भी आमतौर पर समय की बर्बादी है। इस मामले में, जब आप निष्पादित करते हैं ls -d */, तो क्या होता है कि शेल */उपनिर्देशिकाओं की सूची में फैलता है (जो पहले से ही वास्तव में आप क्या चाहते हैं), उस सूची को तर्कों के रूप में पारित करता है ls -d, जो प्रत्येक को देखता है, कहता है "हां, यह एक निर्देशिका है सब ठीक है "और इसे प्रिंट करता है (एक असंगत और कभी-कभी अस्पष्ट प्रारूप में)। lsआदेश में कुछ भी उपयोगी नहीं कर रहा है!

ठीक है, ठीक है, यह एक काम कर रहा है जो उपयोगी है: यदि कोई उपनिर्देशिका नहीं */है, तो जैसा है वैसे ही छोड़ दिया lsजाएगा , "*" नामक उपनिर्देशिका की तलाश करेंगे, इसे न ढूंढें, एक त्रुटि संदेश प्रिंट करें जो कि मौजूद नहीं है (में है) stderr), और "* /" (stdout में) प्रिंट न करें

उपनिर्देशिका नामों की एक सरणी बनाने के लिए क्लीनर तरीका है कि इसे पास किए बिना ग्लोब ( */) का उपयोग किया जाए । लेकिन सरणी में "* /" डालने से बचने के लिए अगर कोई वास्तविक उपनिर्देशिका नहीं है, तो आपको पहले नलग्लोब सेट करना चाहिए (फिर से, ग्रेग की विकि देखें ):ls

shopt -s nullglob
array=(*/)
shopt -u nullglob # Turn off nullglob to make sure it doesn't interfere with anything later
echo "${array[@]}"  # Note double-quotes to avoid extra parsing of funny characters in filenames

यदि आप कोई त्रुटि संदेश मुद्रित करना चाहते हैं यदि कोई उपनिर्देशिका नहीं है, तो आप इसे स्वयं करना बेहतर मानते हैं:

if (( ${#array[@]} == 0 )); then
    echo "No subdirectories found" >&2
fi

2
आपकी टिप्पणी के लिए धन्यवाद, भले ही जवाब के रूप में चिह्नित नहीं किया गया था यह काफी जानकारीपूर्ण था और मैं इसकी सराहना करता हूं।
जेक एच

अगर आपको /dir नाम नहीं चाहिए तो क्या होगा ?
shinzou

Greg की विकी में उल्लिखित समस्याएं / मुद्दे ऐसी चीजें नहीं हैं, जिन्हें आसानी से मात्र सशर्त निर्माणों के साथ निपटाया नहीं जा सकता है। lsएक साधारण आदेश है। यह आउटपुट स्ट्रिंग्स है। बैरिंग पार्सिंग स्ट्रिंग्स में अत्यधिक अच्छा है। उचित रेगेक्स वह सब है जो सुरक्षित रूप से lsआउटपुट को पार्स करने के लिए आवश्यक है ।
योकाई

@ योकाई विभिन्न नामों को फिल्नामों में lsअजीब / गैर-चरित्र वाले पात्रों के साथ करते हैं, इसलिए इसका उत्पादन फिल्माने की सूची में पार्स करने का कोई सुसंगत तरीका नहीं है। और जैसा कि मैंने कहा, यह वास्तव में कुछ भी उपयोगी नहीं है: यदि आप सही तरीके से आउटपुट को पार्स करते हैं ls -d */, तो आप ठीक उसी चीज़ से हवा निकालेंगे जो आपको सीधे मिलेगी */(जब कोई मैच नहीं हैं, और इसके लिए जांच करना आसान है)।
गॉर्डन डेविसन

इसलिए सारांशित करने के लिए: A lazy sysadmin is a good sysadmin.शायद मेरा अपना lsपार्सिंग उस संस्करण के लिए विशिष्ट है जो मेरे पास है, या जिसका मैं उपयोग कर रहा हूं, लेकिन अभी तक उनके पास लिनक्स डिस्ट्रोस पर कोई समस्या नहीं है जो मैंने उन पर परीक्षण किया है। मैं केवल अनुभव से बोल सकता हूं।
योकाई

8

यह उन निर्देशिकाओं में फ़ाइलों को लाइन से प्रिंट करेगा।

array=(ww/* ee/* qq/*)
printf "%s\n" "${array[@]}"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.