कई फ़ाइलों को सम्‍मिलित करें लेकिन अनुभाग हेडर के रूप में फ़ाइल नाम शामिल करें


354

मैं टर्मिनल में एक बड़ी फ़ाइल में कई पाठ फ़ाइलों को संक्षिप्त करना चाहूंगा। मुझे पता है कि मैं बिल्ली कमांड का उपयोग करके ऐसा कर सकता हूं। हालाँकि, मैं प्रत्येक फ़ाइल का फ़ाइल नाम उस फ़ाइल के लिए "डेटा डंप" से पहले करना चाहूंगा। क्या कोई जानता है कि इसे कैसे करना है?

वर्तमान में मेरे पास क्या है:

file1.txt = bluemoongoodbeer

file2.txt = awesomepossum

file3.txt = hownowbrowncow

cat file1.txt file2.txt file3.txt

वांछित उत्पादन:

file1

bluemoongoodbeer

file2

awesomepossum

file3

hownowbrowncow

मैं वास्तव में कुछ ऐसा ही करने के लिए uuencode & uudecode का उपयोग कर रहा हूं, मुझे फ़ाइल पठनीय इनबेटीइन की आवश्यकता नहीं है, केवल परिणाम की आवश्यकता है और उन्हें फिर से किसी अन्य कमांड पर पाइप करें

जवाबों:


532

उसी चीज़ की तलाश में था, और यह सुझाव देने के लिए मिला:

tail -n +1 file1.txt file2.txt file3.txt

आउटपुट:

==> file1.txt <==
<contents of file1.txt>

==> file2.txt <==
<contents of file2.txt>

==> file3.txt <==
<contents of file3.txt>

यदि केवल एक ही फाइल है तो हेडर प्रिंट नहीं किया जाएगा। यदि जीएनयू बर्तनों का उपयोग कर रहे हैं, तो आप -vहमेशा हेडर प्रिंट करने के लिए उपयोग कर सकते हैं ।


2
यह GNU टेल (GNU Coreutils का हिस्सा) के साथ भी काम करता है।
अर्जुनशंकर

8
बहुत बढ़िया -n +1विकल्प! एक विकल्प head -n-0 file1 file2 file3:।
फ्रोजन फ्लेम

3
वर्क्स दोनों बीएसडी पूंछ और MacOS एक्स आप पर जीएनयू पूंछ के साथ महान के बीच की जगह को छोड़ कर सकते हैं -nऔर +1के रूप में, -n+1
vdm

4
tail -n +1 *वास्तव में मैं देख रहा था, धन्यवाद!
kR105

1
MacOsX 10.14.4 पर काम करता हैsudo ulimit -n 1024; find -f . -name "*.rb" | xargs tail -n+1 > ./source_ruby.txt
कोलाज़

187

मैंने कुछ इसी तरह के लिए grep का इस्तेमाल किया:

grep "" *.txt

यह आपको 'हेडर' नहीं देता है, लेकिन फ़ाइल नाम के साथ हर पंक्ति को उपसर्ग करता है।


10
आउटपुट *.txtकेवल एक फ़ाइल तक फैलता है तो टूट जाता है । इस संबंध में, मैं सलाह देंगेgrep '' /dev/null *.txt
antak

1
मुझे grep के लिए एक नया उपयोग दिखाने के लिए +1। यह मेरी जरूरतों को पूरी तरह से पूरा किया। मेरे मामले में, प्रत्येक फ़ाइल में केवल एक ही लाइन होती थी, इसलिए इसने मुझे बड़े करीने से तैयार किया हुआ आउटपुट दिया जो आसानी से पार्स करने योग्य था
21

9
grepएक से अधिक फ़ाइल होने पर केवल फ़ाइल हेडर प्रिंट करेगा। यदि आप फ़ाइल पथ को हमेशा प्रिंट करना सुनिश्चित करना चाहते हैं, तो उपयोग करें -H। यदि आप हेडर का उपयोग नहीं करना चाहते हैं -h। यह भी ध्यान दें कि यह (standard input)STDIN के लिए प्रिंट होगा ।
जॉर्ज बुकेरन

1
आप ag(चांदी खोजकर्ता) का उपयोग भी कर सकते हैं : डिफ़ॉल्ट रूप से, ag . *.txtप्रत्येक फ़ाइल को उसके नाम के साथ, और प्रत्येक पंक्ति को उसके नंबर के साथ उपसर्ग करता है।
अनोल

1
ध्यान दें, -ngrep को पास करने से भी लाइन नंबर मिलते हैं जो आपको पिनपिनिंग के साथ साधारण लिंटर लिखने की अनुमति देता है जो कि, जैसे, emacs द्वारा उठाया जा सकता है।
डिप्रैडडैनियल

105

यह चाल के रूप में अच्छी तरह से करना चाहिए:

find . -type f -print -exec cat {} \;

माध्यम:

find    = linux `find` command finds filenames, see `man find` for more info
.       = in current directory
-type f = only files, not directories
-print  = show found file
-exec   = additionally execute another linux command
cat     = linux `cat` command, see `man cat`, displays file contents
{}      = placeholder for the currently found filename
\;      = tell `find` command that it ends now here

आप आगे की तरह गर्त बूलियन ऑपरेटरों को जोड़ सकते हैं -andया -orfind -lsअच्छा है, भी है।


1
क्या आप अधिक बता सकते हैं कि यह कमांड क्या करता है? क्या वास्तव में मुझे इसकी आवश्यकता है
AAlvz

5
यह linux 'standard find कमांड है। यह वर्तमान निर्देशिका में सभी फ़ाइलों को खोजता है, उनके नाम को प्रिंट करता है, फिर प्रत्येक के लिए, फ़ाइल को कैट करता है। -printइससे पहले फ़ाइल नाम नहीं छोड़ेगा cat
Maxim_united

18
आप -printfआउटपुट को अनुकूलित करने के लिए भी उपयोग कर सकते हैं । उदाहरण के लिए: find *.conf -type f -printf '\n==> %p <==\n' -exec cat {} \;के उत्पादन से मेल खाने के लिएtail -n +1 *
Maxim_united

1
-प्रिंटफ मैक पर काम नहीं करता है, जब तक कि आप नहीं चाहते हैं brew install findutilsऔर gfindइसके बजाय उपयोग करें find
मैट फ्लेचर

2
यदि आप चाहते हैं कि रंग आप उस तथ्य का उपयोग कर सकते हैं जो findकई -execएस की अनुमति देता है :find -name '*.conf' -exec printf '\n\e[33;1m%s\e[0m\n' {} \; -exec cat {} \;
प्रतिबंध

24

यह काम कर जाना चाहिए:

for filename in file1.txt file2.txt file3.txt; do
    echo "$filename"
    cat "$filename"
done > output.txt

या सभी पाठ फ़ाइलों के लिए ऐसा करने के लिए पुनरावर्ती:

find . -type f -name '*.txt' -print | while read filename; do
    echo "$filename"
    cat "$filename"
done > output.txt

1
काम नहीं किया। मैंने अभी कुछ बहुत ही बदसूरत awk कोड लिखे: i for $ listoffiles do awk '{Print FILENAME, $ 0, $ 1, $ 2, $ 3, $ 4, $ 5, $ 6, $ 6, $ 7, $ 8, $ 9, $ 10}, $ 11}' $ i >> concat.txt किया
निक

2
...विस्तृत करने के लिए परवाह? के बारे में के रूप में सरल के रूप में के रूप में बैश कोड हो जाता है।
क्रिस एबरले

@ निक: आपकी awk लाइन भी काम नहीं करना चाहिए, यह देखते हुए कि $0यह पूरी लाइन है, इसलिए आप वास्तव में वहाँ कॉलम दोहरा रहे हैं ...
क्रिस Eberle

@ निक: निफ्टी समाधान अन्यथा :)
क्रिस

@ क्रिस: हाँ, लेकिन यह एक बहुत बदसूरत से मैं यह होना चाहते हैं। हो सकता है कि आपका कोड मेरे लिए काम नहीं कर रहा था क्योंकि मैं stdout को पकड़ने के लिए >> का उपयोग कर रहा हूं?
निक

17

मेरे पास फ़ाइलों की एक श्रंखला थी, जो सांख्यिकी में समाप्त हो गई थी। यह कि मैं फ़ाइल नाम के साथ सहमति बनाना चाहता था।

मैंने निम्नलिखित किया और जब एक से अधिक फ़ाइल होती हैं, तो "अधिक" कमांड में एक हेडर के रूप में फ़ाइल नाम शामिल होता है।

more *stats.txt > stats.txt

या एक सामान्य मामले के लिए

more FILES_TO_CONCAT > OUTPUT_FILE

6
more <FILES> | cat
एक्यूमेनस

15
find . -type f -print0 | xargs -0 -I % sh -c 'echo %; cat %'

यह पूरा फ़ाइल नाम (पथ सहित) प्रिंट करेगा, फिर फ़ाइल की सामग्री। यह बहुत लचीला भी है, क्योंकि आप फ़ाइंड कमांड के लिए -name "expr" का उपयोग कर सकते हैं, और फ़ाइलों पर अपनी पसंद के अनुसार कई कमांड चला सकते हैं।


1
इसके साथ गठबंधन करना भी काफी सरल है grep। के साथ उपयोग करने के लिए bash:find . -type f -print | grep PATTERN | xargs -n 1 -I {} -i bash -c 'echo ==== {} ====; cat {}; echo'
dojuba

5

यह है कि मैं आम तौर पर इस तरह स्वरूपण को संभालता हूं:

for i in *; do echo "$i"; echo ; cat "$i"; echo ; done ;

मैं आम तौर पर बिल्ली को विशिष्ट जानकारी के लिए एक ग्रीप में पाइप करता हूं।


3
यहां सावधान रहें। for i in *उपनिर्देशिका शामिल नहीं होगी।
एक्यूमेनस

5

मुझे यह विकल्प पसंद है

for x in $(ls ./*.php); do echo $x; cat $x | grep -i 'menuItem'; done

आउटपुट इस तरह दिखता है:

./debug-things.php
./Facebook.Pixel.Code.php
./footer.trusted.seller.items.php
./GoogleAnalytics.php
./JivositeCode.php
./Live-Messenger.php
./mPopex.php
./NOTIFICATIONS-box.php
./reviewPopUp_Frame.php
            $('#top-nav-scroller-pos-<?=$active**MenuItem**;?>').addClass('active');
            gotTo**MenuItem**();
./Reviews-Frames-PopUps.php
./social.media.login.btns.php
./social-side-bar.php
./staticWalletsAlerst.php
./tmp-fix.php
./top-nav-scroller.php
$active**MenuItem** = '0';
        $active**MenuItem** = '1';
        $active**MenuItem** = '2';
        $active**MenuItem** = '3';
./Waiting-Overlay.php
./Yandex.Metrika.php

5

और लापता awk समाधान है:

$ awk '(FNR==1){print ">> " FILENAME " <<"}1' *

आपके शानदार जवाब के लिए धन्यवाद। क्या आप 1अभिव्यक्ति के अंत में इसका अर्थ समझा सकते हैं ?
bwangel

1
धन्यवाद। आप एक नज़र डाल सकते हैं कि awk script के अंत में 1 का अर्थ क्या है
kvantour

3

आप लूप का उपयोग करने के बजाय इस सरल कमांड का उपयोग कर सकते हैं,

ls -ltr | awk '{print $9}' | xargs head

3

यदि आपको रंग पसंद हैं, तो यह आज़माएँ:

for i in *; do echo; echo $'\e[33;1m'$i$'\e[0m'; cat $i; done | less -R

या:

tail -n +1 * | grep -e $ -e '==.*'

या: (पैकेज 'मल्टीटेल' के साथ)

multitail *

1
फ़ाइल नाम को उजागर करने वाले रंगों के लिए:find . -type f -name "*.txt" | xargs -I {} bash -c "echo $'\e[33;1m'{}$'\e[0m';cat {}"
MediaVince

3

यदि सभी फ़ाइलों का नाम समान है या findआपके द्वारा मेल किया जा सकता है , तो आप कर सकते हैं (जैसे):

find . -name create.sh | xargs tail -n +1

खोजने के लिए, प्रत्येक फ़ाइल का पथ और बिल्ली दिखाएं।


2

यहाँ एक बहुत ही सरल तरीका है। आपने कहा कि आप बिल्ली करना चाहते हैं, जिसका अर्थ है कि आप पूरी फ़ाइल देखना चाहते हैं। लेकिन आपको फ़ाइल नाम मुद्रित करने की भी आवश्यकता है।

इसे इस्तेमाल करे

head -n99999999 * या head -n99999999 file1.txt file2.txt file3.txt

उम्मीद है की वो मदद करदे


4
एक क्लीनर सिंटैक्स होगा head -n -0 file.txt file2.txt file3.txtheadग्नू
कोरुटिल्स

1

यह विधि फ़ाइल नाम को मुद्रित करेगी और फिर सामग्री फ़ाइल करेगी:

tail -f file1.txt file2.txt

आउटपुट:

==> file1.txt <==
contents of file1.txt ...
contents of file1.txt ...

==> file2.txt <==
contents of file2.txt ...
contents of file2.txt ...

3
-fयदि आप किसी फ़ाइल जो करने के लिए लिखा जा रहा है ट्रैक करना चाहते हैं, लेकिन वास्तव में नहीं क्या ओपी पूछा के दायरे के भीतर उपयोगी है।
ट्रिपल

1

यदि आप उन बदसूरत को बदलना चाहते हैं ==> <== कुछ और के साथ

tail -n +1 *.txt | sed -e 's/==>/\n###/g' -e 's/<==/###/g' >> "files.txt"

स्पष्टीकरण:

tail -n +1 *.txt - हेडर के साथ फ़ोल्डर में सभी फ़ाइलों को आउटपुट

sed -e 's/==>/\n###/g' -e 's/<==/###/g'- की जगह ==>के साथ नई लाइन + ### और <==बस के साथ ###

>> "files.txt" - सभी एक फ़ाइल के लिए उत्पादन



0

यदि आप अपने वांछित आउटपुट के रूप में उसी प्रारूप में परिणाम चाहते हैं, जिसे आप आज़मा सकते हैं:

for file in `ls file{1..3}.txt`; \
do echo $file | cut -d '.' -f 1; \ 
cat $file  ; done;

परिणाम:

file1
bluemoongoodbeer
file2
awesomepossum
file3
hownowbrowncow

आप echo -eकट के पहले और बाद में रख सकते हैं ताकि आपके पास लाइनों के बीच रिक्ति हो:

$ for file in `ls file{1..3}.txt`; do echo $file | cut -d '.' -f 1; echo -e; cat $file; echo -e  ; done;

परिणाम:

file1

bluemoongoodbeer

file2

awesomepossum

file3

hownowbrowncow

स्पष्टीकरण: forलूप उस सूची के माध्यम से जाता है जो lsकमांड का परिणाम है। $ ls file{1..3}.txtपरिणाम: file1.txt file2.txt file3.txtप्रत्येक पुनरावृत्ति स्ट्रिंग होगी echo, $fileफिर इसे एक cutकमांड में पाइप किया जाता है, जहां मैंने .एक फ़ील्ड विभाजक के रूप में उपयोग किया था, जो fileX.txt को दो टुकड़ों में तोड़ता है और फ़ील्ड 1 को प्रिंट करता है (फ़ील्ड 2 txt है) बाकी स्पष्ट होना चाहिए
फ़ेक सुमेर

0
  • AIX 7.1 ksh

... जिन लोगों ने पहले ही सिर का उल्लेख किया है , उनमें से कुछ के लिए हम पर काम कर रहे हैं:

$ r head
head file*.txt
==> file1.txt <==
xxx
111

==> file2.txt <==
yyy
222
nyuk nyuk nyuk

==> file3.txt <==
zzz
$

मेरी जरूरत पहली पंक्ति को पढ़ने की है; जैसा कि कहा गया है, यदि आप 10 से अधिक लाइनें चाहते हैं, तो आपको विकल्प (हेड -9999, आदि) जोड़ना होगा।

एक व्युत्पन्न टिप्पणी पोस्ट करने के लिए क्षमा करें; मेरे पास किसी की टिप्पणी के लिए टिप्पणी करने / जोड़ने के लिए पर्याप्त स्ट्रीट क्रेडिट नहीं है।


-1

इस कार्य को हल करने के लिए, मैं आमतौर पर निम्नलिखित कमांड का उपयोग करता हूं:

$ cat file{1..3}.txt >> result.txt

यदि फ़ाइलों की संख्या काफी बड़ी है, तो फाइलों को संक्षिप्त करना बहुत सुविधाजनक तरीका है।


1
लेकिन यह ओपी के सवाल का जवाब नहीं देता है।
क्वांटूर

-3

पहले मैंने प्रत्येक फ़ाइल बनाई: प्रत्येक फ़ाइल [123] .txt के लिए 'जानकारी'> file1.txt।

फिर मैंने प्रत्येक फ़ाइल को यह सुनिश्चित करने के लिए छापा कि जानकारी सही थी: पूंछ फ़ाइल?

फिर मैंने ऐसा किया: पूंछ फ़ाइल? .Txt >> Mainfile.txt। इसने प्रत्येक फ़ाइल में जानकारी को मुख्य फ़ाइल में संग्रहीत करने के लिए Mainfile.txt बनाया।

cat Mainfile.txt ने पुष्टि की कि यह ठीक है।

==> file1.txt <== bluemoongoodbeer

==> file2.txt <== भयानकपॉसम

==> file3.txt <== hownowbrowncow

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.