कस्टम सीमांकक के साथ फ़ाइल नामों की कई पंक्तियों को एक में कैसे शामिल किया जाए?


441

मैं ls -1एक पंक्ति के परिणाम में शामिल होना चाहूंगा और जो कुछ भी चाहता हूं उसके साथ इसे परिसीमित करूंगा ।

क्या इसे प्राप्त करने के लिए किसी भी मानक लिनक्स कमांड का उपयोग किया जा सकता है?

जवाबों:


689

बहुत पहले विकल्प के समान है, लेकिन अनुगामी परिसीमन को छोड़ देता है

ls -1 | paste -sd "," -

29
बस एक नोट के रूप में, मेरे द्वारा कोशिश किए गए पेस्ट के संस्करण को STDIN से पढ़ने के लिए बताने के लिए अंत में एक "-" तर्क की आवश्यकता है। उदाहरण के लिए ls -1 | paste -s -d ":" - यदि पेस्ट के सभी संस्करणों के साथ सार्वभौमिक है, तो यह निश्चित नहीं है
एंडी व्हाइट

4
यह बेहतर है क्योंकि यह खाली परिसीमन की अनुमति देता है :)
Yura Purbeev

2
नोट डिफ़ॉल्ट रूप में (मानक इनपुट) pasteमिलता है -, कम से कम मेरे पर paste (GNU coreutils) 8.22
फेडोरक्वी 'SO रोकना नुकसानदायक'

1
मैंने सिर्फ इसे उकेरा, यह है और अब इसमें चयनित उत्तर के समान वोट हैं। यह उत्तर है। कोई अनुगामी
परिधि

1
खाली सीमांकक का उपयोग करके निर्दिष्ट किया जा सकता है "\0", इसलिए paste -sd "\0" -मेरे लिए काम किया!
ब्रैड पार्क 20

379

संपादित करें : बस " ls -M " यदि आप चाहते हैं एक अल्पविराम होने के लिए अपने सीमांकक

आह, शक्ति और सादगी!

ls -1 | tr '\n' ','

अल्पविराम बदलें " , " जो आप चाहते हैं। ध्यान दें कि इसमें "ट्रेलिंग कॉमा" शामिल है


46
+1, लेकिन एक अधिक विस्तृत संस्करण को अंतिम \ n अलग ढंग से संभालना चाहिए
mouviciel

5
यदि फ़ाइल नाम \nमें यह है, तो यह भी बदल जाएगा।
कोडैडडिक्ट

3
@ श्रीवत्सआर: उसका मतलब है, अनुगामी को नहीं जोड़ना "," मुझे विश्वास है। जैसेls -1 | tr "\\n" "," | sed 's/\(.*\),/\1/'
क्रिस

7
@ क्रिस: sedएंड-मार्कर चरित्र के साथ आपका थोड़ा और कुशल हो सकता है:ls -1 | tr "\\n" "," | sed 's/,$//'; echo ''
pieman72

2
अंतिम प्रतीक को हटाने के लिए लगता है के sedबाद का उपयोग करना trअनुचित लगता है। मैं साथ जाता हूँls -1 | tr '\n' ',' | head -c -1
reddot

29

यह अंतिम अल्पविराम को एक नई पंक्ति के साथ प्रतिस्थापित करता है:

ls -1 | tr '\n' ',' | sed 's/,$/\n/'

ls -m स्क्रीन-चौड़ाई के चरित्र में नए उदाहरण शामिल हैं (उदाहरण के लिए 80 वें)।

ज्यादातर बैश (केवल lsबाहरी):

saveIFS=$IFS; IFS=$'\n'
files=($(ls -1))
IFS=,
list=${files[*]}
IFS=$saveIFS

बाश 4 में readarray(उर्फ mapfile) का उपयोग करना :

readarray -t files < <(ls -1)
saveIFS=$IFS
IFS=,
list=${files[*]}
IFS=$saveIFS

सुझावों के लिए gniourf_gniourf का धन्यवाद।


यह नाम में सफेद रिक्त स्थान वाली फ़ाइलों का ध्यान नहीं रखेगा। इसे आज़माएँ: dir = / tmp / testdir; rm -rf $ dir && mkdir $ dir && cd / $ dir && स्पर्श "यह एक फ़ाइल है" this_is_another_file && ls -1 && files = ($ (l0 -1)) && सूची = $ {फाइलें [@] /% /% ,} && सूची = $ {सूची% *,} और& गूंज $ सूची
मंद

1
@ डैमिर: इस सवाल के कई जवाब इस समस्या से ग्रस्त हैं। मैंने टैब या रिक्त स्थान के साथ फ़ाइल नाम की अनुमति देने के लिए अपना उत्तर संपादित किया है, लेकिन नई सूचियाँ नहीं।
अगली सूचना तक रोक दिया गया।

आपका बैश संस्करण pathname विस्तार से भी ग्रस्त है। लाइनों से एक सरणी का निर्माण करने के लिए, प्रयोग करने पर विचार कृपया mapfileके रूप में (बैश ≥4): mapfile -t files < <(ls -1)। के साथ बेला करने की कोई जरूरत नहीं है IFS। और यह छोटा भी है।
गनीउर_गनीउरफ

और जब आपके पास आपकी सरणी हो, तो आप IFSफ़ील्ड में शामिल होने के लिए उपयोग कर सकते हैं saveIFS=$IFS; IFS=,; list=${files[*]}; IFS=$saveIFS:। या यदि आप एक वर्ण के साथ एक विभाजक चाहते हैं तो दूसरी विधि का उपयोग करें।
गनीउरफ_गनीउरफ

1
@gniourf_gniourf: मैंने अपने सुझावों को अपने उत्तर में शामिल किया है। धन्यवाद।
अगली सूचना तक रोक दिया गया।

24

मुझे लगता है कि यह एक कमाल है

ls -1 | awk 'ORS=","'

ORS "आउटपुट रिकॉर्ड सेपरेटर" है, इसलिए अब आपकी लाइनें अल्पविराम से जुड़ जाएंगी।


6
यह अनुगामी परिसीमन को बाहर नहीं करता है।
डेरेक महार

6
मल्टी-कैरेक्टर रिकॉर्ड सेपरेटर (जैसे " OR ") से निपटने के कारण यह विशेष रूप से भयानक है
मैट शेफ़र

15

सेटिंग IFSऔर उपयोग का संयोजन "$*"आप जो चाहते हैं वह कर सकते हैं। मैं एक उपखंड का उपयोग कर रहा हूं इसलिए मैं इस शेल के $ IFS के साथ हस्तक्षेप नहीं करता हूं

(set -- *; IFS=,; echo "$*")

आउटपुट कैप्चर करने के लिए,

output=$(set -- *; IFS=,; echo "$*")

2
क्या आपके पास कुछ और जानकारी है कि कैसे setकाम करता है? मुझे वूडू की तरह थोड़ा सा दिखता है। उथली नज़र के माध्यम से man setमुझे बहुत जानकारी शुद्ध नहीं था।
एहतेश चौधरी

3
यदि आप setतर्कों का एक गुच्छा देते हैं, लेकिन कोई विकल्प नहीं है, तो यह स्थितिगत मापदंडों ($ 1, $ 2, ...) को निर्धारित करता है। पहला तर्क (या इस मामले में फ़ाइल नाम) के मामले में --रक्षा करने के लिए setहोता है जो डैश के साथ शुरू होता है। में --विकल्प का विवरण देखें help set। मैं चीजों की एक सूची को संभालने के लिए स्थितीय मापदंडों को एक सुविधाजनक तरीका ढूंढता हूं। मैं इसे एक सरणी के साथ भी लागू कर सकता था:output=$( files=(*); IFS=,; echo "${files[*]}" )
ग्लेन जैकमैन

यह बहुत अच्छा है क्योंकि इसमें किसी भी अतिरिक्त प्रोग्राम को निष्पादित करने की आवश्यकता नहीं होती है और यह उन फ़ाइल नामों के साथ काम करता है जिनमें रिक्त स्थान या यहां तक ​​कि newlines भी होते हैं।
एरिक

1
@EhteshChoudhury के रूप में type set, आपको बता देंगे set is a shell builtin। तो, man setमदद नहीं करेगा, लेकिन help setकरेगा। उत्तर: "- स्थितिगत मापदंडों के लिए किसी भी शेष तर्क को असाइन करें।"
स्टीफन गौरीचोन

के बाद ए set -- **एक स्तर के विस्तार में देरी से आपको उप शेल की आवश्यकता के बिना सही आउटपुट मिल सकता है IFS=',' eval echo '"$*"':। बेशक जो स्थितिगत मापदंडों को बदल देगा।
इसहाक

13

lsसामान्य रूप से पार्स करने की सलाह नहीं दी जाती है , इसलिए उपयोग करने के लिए वैकल्पिक बेहतर तरीका है find, उदाहरण के लिए:

find . -type f -print0 | tr '\0' ','

या का उपयोग करके findऔर paste:

find . -type f | paste -d, -s

सामान्य रूप से कई लाइनों (फाइल सिस्टम से संबंधित नहीं) में शामिल होने के लिए , जांच करें: यूनिक्स कमांड-लाइन पर संक्षिप्त और पोर्टेबल "जॉइन" करें


9

पहिया को सुदृढ़ मत करो।

ls -m

यह बिल्कुल वैसा ही करता है।


ओपी कोई भी परिसीमन चाहता था, इसलिए आपको अल्पविराम को बदलने के लिए अभी भी एक tr की आवश्यकता होगी। यह कॉमास के बाद एक स्थान भी जोड़ता है अर्थात फ़ाइल 1, फ़ाइल 2, फाइल 3
रोब

इसलिए का उपयोग करके ls -mऔर trअल्पविराम के बाद अंतरिक्ष को हटाने के लिएls -m | tr -d ' '
एंडी

2
कि tr का उपयोग फ़ाइल नाम के अंदर रिक्त स्थान को हटा देगा। बेहतर उपयोग करने के लिएsed 's/, /,/g
ग्लेन जैकमैन

7

बस बकवास

mystring=$(printf "%s|" *)
echo ${mystring%|}

5
थोड़ा और अधिक कुशल "printf -v mystring"% s का उपयोग किया जाएगा | "*" - कि के लिए $ () एक कांटा से बचा जाता है
camh

लेकिन विशेष रूप से अनुगामी |, @camh chomp नहीं है ।
क्रिस्टोफर

1
ठीक है, बस bashऔर printf
गनु कोरुटिल्स

@camh printf -vकेवल बैश में काम करेगा, जबकि प्रस्तुत उत्तर कई शेल प्रकारों पर काम करता है।
इसहाक

@ क्रिस्‍टोफर हां, यह अनुगामी हटा देगा |, बशर्ते कि दोनों पंक्तियों का उपयोग किया जाए printf -v mystring "%s|" * ; echo ${mystring%|}:।
आइजैक

7

यह आदेश PERL प्रशंसकों के लिए है:

ls -1 | perl -l40pe0

यहां 40 स्पेस के लिए ऑक्टल अस्की कोड है।

-p लाइन और प्रिंट द्वारा लाइन प्रोसेस करेगा

-लगता है कि हम प्रदान करने वाले एएससीआई चरित्र के साथ ट्रेलिंग \ n को बदलने का ख्याल रखेंगे।

-हम पेरल को सूचित करना है कि हम कमांड लाइन निष्पादन कर रहे हैं।

0 का मतलब है कि निष्पादित करने के लिए वास्तव में कोई आदेश नहीं है।

perl -e0 perl -e के समान है ''


6

Tr के लिए संभावित न्यूलाइन भ्रम से बचने के लिए हम -b फ्लैग को ls में जोड़ सकते हैं:

ls -1b | tr '\n' ';'

5

ऐसा लगता है कि उत्तर पहले से मौजूद हैं।

यदि आप a, b, cप्रारूप चाहते हैं , तो ls -m( टुलेंस कोर्डोवा का उत्तर ) का उपयोग करें

या यदि आप a b cप्रारूप चाहते हैं , तो उपयोग करें ls | xargs( क्रिस जे के उत्तर का अनुकरण संस्करण )

या यदि आप कोई अन्य परिसीमन चाहते हैं |, तो उपयोग करें ls | paste -sd'|'( आर्टेम के उत्तर का आवेदन )


5

मेजकिनेटोर के उत्तर के शीर्ष पर जोड़कर, ट्रेलिंग सीमांकक को हटाने का तरीका है (क्योंकि मैं अभी उसके उत्तर के तहत टिप्पणी नहीं कर सकता):

ls -1 | awk 'ORS=","' | head -c -1

के रूप में अपने सीमांकक मायने रखता है बस के रूप में कई अनुगामी बाइट्स को हटा दें।

मुझे यह तरीका पसंद है क्योंकि मैं मल्टी कैरेक्टर सीमांकक + के अन्य लाभों का उपयोग कर सकता हूं awk:

ls -1 | awk 'ORS=", "' | head -c -2

संपादित करें

जैसा कि पीटर ने देखा है, नकारात्मक बाइट गिनती देशी मैकओएस संस्करण में समर्थित नहीं है। यह हालांकि आसानी से तय किया जा सकता है।

सबसे पहले, स्थापित करें coreutils। "जीएनयू कोर यूटिलिटीज जीएनयू ऑपरेटिंग सिस्टम की मूल फ़ाइल, शेल और टेक्स्ट हेरफेर यूटिलिटीज हैं।"

brew install coreutils

MacOS द्वारा प्रदान किए गए कमांड भी उपसर्ग "जी" के साथ स्थापित होते हैं। उदाहरण के लिए gls

एक बार जब आप ऐसा कर लेते हैं, तो आप उपयोग कर सकते हैं gheadजिसमें नकारात्मक बाइट की गिनती होती है, या बेहतर, उर्फ ​​बनाते हैं:

alias head="ghead"

नोट: नकारात्मक बाइट काउंट केवल सिर के कुछ संस्करणों पर समर्थित होते हैं, इसलिए यह उदाहरण के macos पर काम नहीं करेगा।
पीटर

यह बात बताने के लिए धन्यवाद। मैंने MacOS के लिए वर्कअराउंड जोड़ा है।
अलेक्जेंडर स्टेलमज़ोनक

4

तलछट रास्ता,

sed -e ':a; N; $!ba; s/\n/,/g'
  # :a         # label called 'a'
  # N          # append next line into Pattern Space (see info sed)
  # $!ba       # if it's the last line ($) do not (!) jump to (b) label :a (a) - break loop
  # s/\n/,/g   # any substitution you want

नोट :

यह जटिलता में रैखिक है, सभी लाइनों को एक बार सेड के पैटर्न स्पेस में जोड़ने के बाद ही प्रतिस्थापित किया जाता है।

@ AnandRajaseka का उत्तर , और कुछ अन्य समान उत्तर, जैसे कि यहाँ , O (n²) हैं, क्योंकि sed को हर बार एक नई लाइन को पैटर्न स्पेस में जोड़ा जाता है।

तुलना करना,

seq 1 100000 | sed ':a; N; $!ba; s/\n/,/g' | head -c 80
  # linear, in less than 0.1s
seq 1 100000 | sed ':a; /$/N; s/\n/,/; ta' | head -c 80
  # quadratic, hung

3

यदि आप xargs का संस्करण -d ध्वज का समर्थन करते हैं तो यह काम करना चाहिए

ls  | xargs -d, -L 1 echo

-d परिसीमन ध्वज है

यदि आपके पास -d नहीं है, तो आप निम्नलिखित की कोशिश कर सकते हैं

ls | xargs -I {} echo {}, | xargs echo

पहला xargs आपको अपना सीमांकक निर्दिष्ट करने की अनुमति देता है जो इस उदाहरण में एक अल्पविराम है।


3
-dजीएनयू xargs के साथ इनपुट सीमांकक निर्दिष्ट करता है, इसलिए काम नहीं करेगा। दूसरा उदाहरण अंत में एक आवारा सीमांकक के अन्य समाधान के रूप में एक ही मुद्दे को प्रदर्शित करता है।
थोर

3
sed -e :a -e '/$/N; s/\n/\\n/; ta' [filename]

स्पष्टीकरण:

-e- निष्पादित करने के लिए एक आदेश को दर्शाता है
:a- एक लेबल है
/$/N- वर्तमान और (एन) एक्सट्रीम लाइन के लिए मैच के दायरे को परिभाषित करता है
s/\n/\\n/;- सभी ईओएल की जगह \n
ta;- गोटो लेबल यदि मैच सफल होता है

मेरे ब्लॉग से लिया गया ।



2

lsएक पाइप से जुड़े होने पर एक कॉलम आउटपुट का उत्पादन होता है, इसलिए -1यह बेमानी है।

यहां बिलिन joinफ़ंक्शन का उपयोग करके एक और पर्ल उत्तर दिया गया है जो एक अनुगामी परिसीमन नहीं छोड़ता है:

ls | perl -F'\n' -0777 -anE 'say join ",", @F'

अस्पष्ट -0777बनाता है कि प्रोग्राम चलाने से पहले सभी इनपुट को पढ़ लिया जाए।

sed विकल्प जो अनुगामी परिसीमन को नहीं छोड़ता है

ls | sed '$!s/$/,/' | tr -d '\n'

0

lsएक अल्पविराम और एक स्थान के -mसाथ आउटपुट को परिसीमित करने का विकल्प ", "है।

ls -m | tr -d ' ' | tr ',' ';'

trअंतरिक्ष या अल्पविराम को हटाने के लिए इस परिणाम को पाइप करने से आप trपरिसीमन को बदलने के लिए फिर से परिणाम को पाइप कर सकेंगे ।

मेरे उदाहरण में मैं सीमांकक को सीमांकक के ,साथ प्रतिस्थापित करता हूं;

आप ;जो भी एक चरित्र सीमांकक के साथ बदलना चाहते हैं, क्योंकि tr केवल उन तर्कों के रूप में पारित होने वाले पहले चरित्र के लिए खाता है।


0

आप एक लाइन में कई लाइन मर्ज करने के लिए chomp का उपयोग कर सकते हैं:

perl -e 'जबकि (<>) {if (/ \ $ /) {chomp; } प्रिंट;} 'bad0> परीक्षण

अगर स्टेटमेंट में लाइन ब्रेक कंडीशन है। यह विशेष चरित्र या कोई सीमांकक हो सकता है।


0

अनुगामी स्लैश हैंडलिंग के साथ त्वरित पर्ल संस्करण:

ls -1 | perl -E 'say join ", ", map {chomp; $_} <>'

समझाना:

  • perl -E: सुविधाओं का समर्थन के साथ पर्ल निष्पादित (कहते हैं, ...)
  • कहते हैं: एक वाहक वापसी के साथ प्रिंट करें
  • ",", ARRAY_HERE में शामिल हों: "," के साथ एक सरणी में शामिल हों
  • नक्शा {chomp; $ _} ROWS: प्रत्येक पंक्ति से वाहक वापस लौटें और परिणाम लौटाएं
  • <>: स्टडिन, प्रत्येक पंक्ति एक ROW है, एक मैप के साथ युग्मन यह प्रत्येक ROW की एक सरणी बनाएगा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.