एक फाइल में टेक्स्ट को प्रीपेन्ड करने के लिए यूनिक्स कमांड


126

क्या टेक्स्ट फ़ाइल में कुछ स्ट्रिंग डेटा को प्रस्तुत करने के लिए एक यूनिक्स कमांड है?

कुछ इस तरह:

prepend "to be prepended" text.txt

क्या आप एक एकल कमांड की तलाश कर रहे हैं, या एक छोटी सी स्क्रिप्ट / उर्फ ​​कमांड ठीक है?
लेवोन

2
यदि आप सभी उत्तरों को जोड़ते हैं, तो यह संभवतः सबसे कॉम्पैक्ट तरीका है:<<(echo "to be prepended") < text.txt | sponge text.txt
श्रीधर सरनोबत

यह सवाल वास्तव में बहुत से लोगों में रचनात्मकता लाया है!
रिचर्ड जेसोप

जवाबों:


111
sed -i.old '1s;^;to be prepended;' inFile
  • -iयदि कोई एक्सटेंशन दिया जाता है तो स्थान में परिवर्तन लिखता है और बैकअप लेता है। (इस मामले में .old)
  • 1s;^;to be prepended;दिए गए प्रतिस्थापन स्ट्रिंग द्वारा पहली पंक्ति की शुरुआत का विकल्प देता है, ;एक कमांड सीमांकक के रूप में उपयोग करते हुए ।

19
यदि आप कमांड के साथ कुछ स्पष्टीकरण जोड़ सकते हैं तो यह दूसरों के लिए मददगार होगा जो सेड के कामकाज से परिचित नहीं हैं। ओपी \nप्रेपेंड के बाद डालना चाह सकता है ; उनकी जरूरतों पर निर्भर करता है। नीट समाधान।
लेवोन

हाँ, एक स्पष्टीकरण बहुत अच्छा होगा। क्या inFileइसमें निर्देशिका को शामिल किया जा सकता है ?
zakdances

3
@ लेवन मैं पूरी तरह से एक सम्मिलित करना चाहता था \n। पहले टिप्पणियों को पढ़ना चाहिए। अरे नहीं।
चिशकु

मेरे मामले में मैं पहले से तय लाइन के अंत में एक अर्ध- '1s;^;my-prepended-line\;\n;'
उपनिवेश रखना

5
ध्यान दें कि '\ n' केवल GNU sed के लिए काम करता है, न कि BSD (जैसे OSX, FreeBSD, आदि)। उन लोगों के साथ अधिक पोर्टेबल होने के लिए, देखें: stackoverflow.com/questions/1421478/…
jwd

164
printf '%s\n%s\n' "to be prepended" "$(cat text.txt)" >text.txt

2
एक पंक्ति में और मूल पाठ फ़ाइल में! यह सही सरल उत्तर है। मैं सुझाव देता हूं कि अतिरिक्त नई लाइन \ n इको-ई "प्रीपेडेड होने के लिए \ n $ (कैट टेक्सट टेक्सट)"> text.txt
VincentPerrin.com

32
इस समाधान में समस्याएँ हैं ... यह "\ n" की घटनाओं को वास्तविक नई लाइनों में परिवर्तित करता है ... समस्याग्रस्त है यदि आप एक कोड फ़ाइल में स्ट्रिंग के साथ प्रिपेंड कर रहे हैं जिसमें "\ n" है।
पॉल गो

1
मैं अपनी फ़ाइल में यह था git config --get-regex $arg | sed -r 's/\t{3}/\\n/g';और यह गड़बड़ कर देता है क्योंकि यह \tऔर परिवर्तित करता है \n
hppyy

8
यह (1) पूरी फ़ाइल को मेमोरी में लोड करता है, और (2) पूरी फाइल को एक कमांड लाइन तर्क में चिपका देता है। साधारण सामान के लिए ठीक है, लेकिन सीमाओं से सावधान रहें।
jwd

2
पिछली बार मैंने कोशिश की थी, मेरा मानना ​​है कि यह वास्तव में बड़ी फ़ाइलों पर टूट जाएगा, जहां बिल्ली ओवरराइट होने से पहले text.txt की संपूर्ण सामग्री को पढ़ने में विफल रहती है। यदि इको पर-ई विकल्प एक समस्या है, तो आप बैश में एक नया उद्धरण या कर सकते हैंecho "to be prepended"$'\n'"$(cat text.txt)"
jbo5112

44

प्रक्रिया प्रतिस्थापन

मुझे आश्चर्य है कि किसी ने भी इसका उल्लेख नहीं किया।

cat <(echo "before") text.txt > newfile.txt

जो स्पष्ट रूप से स्वीकृत उत्तर की तुलना में अधिक स्वाभाविक है (किसी चीज़ को प्रिंट करना और उसे प्रतिस्थापन कमांड में पाइप करना भौगोलिक रूप से काउंटर-सहज ज्ञान युक्त है)।

... और क्या कह रहा है कि spongeआप एक अस्थायी फ़ाइल की जरूरत नहीं है के साथ ऊपर अपहरण अपहरण :

sudo apt-get install moreutils
<<(echo "to be prepended") < text.txt | sponge text.txt

संपादित करें: ऐसा लगता है कि यह बॉर्न शेल में काम नहीं करता है /bin/sh


यहां स्ट्रिंग (केवल zsh)

यहां एक स्ट्रिंग का उपयोग करना - <<<आप कर सकते हैं:

<<< "to be prepended" < text.txt | sponge text.txt

3
यह जवाब मेरे लिए विजेता है। केवल बिल्डिंस के साथ सरल और प्राप्त करने योग्य। अच्छा कार्य!
पीयर्सपीपी

1
@PiersyP मैं सहमत हूँ! इससे आपको बहुत मदद मिली, शुक्रिया श्रीधर-सरनोबत।

समस्या यह है कि 1 फाइल है, 2 फाइलें नहीं हैं। तो जवाब की पहली पंक्ति वास्तव में काम नहीं करती है। अंतिम पंक्ति काम कर सकती है (लेकिन इसके लिए स्पंज की आवश्यकता होती है)।
VasiliNovikov

1
स्पंज क्या करता है?
हेमंत

1
आपके <<(echo "to be prepended") < text.txtऔर <<< "to be prepended" < text.txtकंस्ट्रक्शन बैश में काम नहीं करते हैं; उन्हें zsh की आवश्यकता होती है।
एंडर्स कासोर्ग

32

यह एक संभावना है:

(echo "to be prepended"; cat text.txt) > newfile.txt

आप शायद एक मध्यवर्ती फ़ाइल के आसपास आसानी से नहीं मिलेंगे।

विकल्प (शेल से बचकर बोझिल हो सकते हैं):

sed -i '0,/^/s//to be prepended/' text.txt

रणनीति 1) यहाँ किसी भी उत्तर का सबसे सहज ज्ञान है, मुझे लगता है। और एक मामूली बदलाव cat <(echo "to be prepended") text.txt > newfile.txt :। यह सोचने के लिए आओ, मुझे यकीन नहीं है कि मेरा संबंधित है, इसलिए इम एक अलग उत्तर पोस्ट कर रहा है।
श्रीधर सरनोबत

1
पहला तरीका फ़ाइल अनुमतियों को संरक्षित नहीं करेगा
Xlsx

अनुमतियों को संरक्षित करने का एकमात्र तरीका स्पंज का उपयोग करना है
श्रीधर सरनोबत

20

यह आउटपुट बनाने के लिए काम करेगा। द - का अर्थ है स्टैंडर्ड इनपुट, जो इको से पाइप के माध्यम से प्रदान किया जाता है।

echo -e "to be prepended \n another line" | cat - text.txt

फ़ाइल को फिर से लिखने के लिए एक अस्थायी फ़ाइल की आवश्यकता होती है क्योंकि इनपुट फ़ाइल में वापस पाइप नहीं किया जा सकता है।

echo "to be prepended" | cat - text.txt > text.txt.tmp
mv text.txt.tmp text.txt

2
यह text.txtअनुरोध के अनुसार पाठ को फ़ाइल में प्रस्तुत नहीं करता है, लेकिन इसे stdout पर प्रदर्शित करता है। अगर उत्पादन ओपी के लिए काम करता है, तो एक अलग फाइल में फनल किया जा सकता है
लेवॉन

1
यह निश्चित रूप से "पहले से तैयार होना" और फिर "text.txt" की सामग्री को प्रिंट करेगा। लेकिन मैं चाहता हूँ कि पाठ को फ़ाइल में पूर्व
एक दो तीन

1
और क्या होगा यदि मेरे पास कई-पंक्ति वाला पाठ है? मैं न्यूलाइन चरित्र को कैसे डालूं?
एक दो तीन

यह अच्छा होगा लेकिन बैश इसे पसंद नहीं करता है: $ इको रिवर्टबेस / | cat - web / .htaccess> web / .htaccess cat: web / .htaccess: इनपुट फाइल आउटपुट फाइल है
geek-merlin

14

एडम के जवाब को प्राथमिकता दें

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

echo -e "to be prepended \n another line" | cat - text.txt | sponge text.txt

यह मेरे लिए एकमात्र समाधान था। यह काफी मजेदार है कि मेरे सर्वर का नाम spongebob है।
.मर एन

10

यदि यह इनपुट फ़ाइल को बदलने के लिए स्वीकार्य है :

ध्यान दें:

  • ऐसा करने से अनपेक्षित दुष्प्रभाव हो सकते हैं, विशेष रूप से एक नियमित फ़ाइल के साथ एक सिमलिंक को बदलना, फ़ाइल पर अलग-अलग अनुमतियों के साथ समाप्त होना और फ़ाइल का निर्माण (जन्म) तारीख बदलना।

  • sed -i, जैसा कि प्रिंस जॉन वेस्ले के उत्तर में है , कम से कम मूल अनुमतियों को पुनर्स्थापित करने की कोशिश करता है, लेकिन अन्य सीमाएं भी लागू होती हैं।

यहां एक सरल विकल्प है जो एक अस्थायी फ़ाइल का उपयोग करता है (यह संपूर्ण इनपुट फ़ाइल को उस तरह से मेमोरी में पढ़ने से बचाता है जो शिम का समाधान करता है):

{ printf 'to be prepended'; cat text.txt; } > tmp.txt && mv tmp.txt text.txt

0xC0000022L के समाधान के रूप में एक उपखंड ( ) का उपयोग करने की तुलना में एक समूह कमांड ( { ...; ...; }) का उपयोग करना थोड़ा अधिक कुशल है ।(...; ...)

लाभ हैं:

  • यह नियंत्रित करना आसान है कि क्या नया पाठ पहली पंक्ति में सीधे होना चाहिए या क्या इसे नई पंक्ति (यों) के रूप में डाला जाना चाहिए (केवल तर्क के \nलिए संलग्न करें printf)।

  • sedसमाधान के विपरीत , यह काम करता है यदि इनपुट फ़ाइल खाली है ( 0बाइट्स)।


sedसमाधान यदि इरादे एक या अधिक पहले जोड़ें करने के लिए है सरल किया जा सकता पूरे लाइनों मौजूदा सामग्री के लिए (यह मानते हुए इनपुट फ़ाइल गैर खाली है):

sedके iसमारोह आवेषण पूरे लाइनों:

GNU के साथ sed:

# Prepends 'to be prepended' *followed by a newline*, i.e. inserts a new line.
# To prepend multiple lines, use '\n' as part of the text.
# -i.old creates a backup of the input file with extension '.old'
sed -i.old '1 i\to be prepended' inFile

एक पोर्टेबल संस्करण जो macOS / BSD के साथ भी काम करता है sed:

# Prepends 'to be prepended' *followed by a newline*
# To prepend multiple lines, escape the ends of intermediate
# lines with '\'
sed -i.old -e '1 i\
to be prepended' inFile

ध्यान दें कि \आवश्यक होने के बाद शाब्दिक नई लाइन ।


यदि इनपुट फ़ाइल को जगह में संपादित किया जाना चाहिए (अपनी सभी विशेषताओं के साथ इनोड को संरक्षित करना):

आदरणीय edPOSIX उपयोगिता का उपयोग करना :

ध्यान दें:

  • edसर्वप्रथम इनपुट फ़ाइल को संपूर्ण मेमोरी में पहले पढ़ता है ।

करने के लिए पहली पंक्ति के लिए सीधे पहले जोड़ें (के साथ के रूप में sed, यह नहीं होगा काम करता है, तो इनपुट फ़ाइल पूरी तरह से खाली (है 0बाइट्स)):

ed -s text.txt <<EOF
1 s/^/to be prepended/
w
EOF
  • -sदबाया edस्थिति संदेश।
  • ध्यान दें कि कमांड को edमल्टी-लाइन के रूप में यहां कैसे प्रदान किया जाता है दस्तावेज़ ( <<EOF\n...\nEOF), यानी, स्टड के माध्यम से ; डिफ़ॉल्ट रूप से स्ट्रिंग विस्तार है (खोल चर अंतर्वेशित कर रहे हैं) ऐसे दस्तावेजों में प्रदर्शन किया; कि (जैसे, ) को दबाने के लिए उद्घाटन सीमांकक उद्धृत करें <<'EOF'
  • 1 पहली पंक्ति को वर्तमान रेखा बनाता है
  • फ़ंक्शन sमौजूदा रेखा पर एक रेगेक्स-आधारित स्ट्रिंग प्रतिस्थापन करता है, जैसे sed; आप प्रतिस्थापन पाठ में शाब्दिक नई \सूचियों को शामिल कर सकते हैं , लेकिन उन्हें -स्कैप किया जाना चाहिए ।
  • wइनपुट फ़ाइल के परिणाम वापस लिखता है (परीक्षण के लिए, की जगह wके साथ ,pही करने के लिए प्रिंट परिणाम इनपुट फ़ाइल को संशोधित किए बिना,)।

करने के लिए एक या अधिक पहले जोड़ें पूरे लाइनों :

साथ ही sed, iफ़ंक्शन हमेशा सम्मिलित किए जाने वाले पाठ में एक अनुगामी न्यूलाइन जोड़ता है।

ed -s text.txt <<EOF
0 i
line 1
line 2
.
w
EOF
  • 0 iबनाता है 0(फ़ाइल की शुरुआत) वर्तमान लाइन और सम्मिलित करता है मोड ( i); ध्यान दें कि लाइन नंबर अन्यथा 1आधारित हैं।
  • निम्न पंक्तियाँ वर्तमान पंक्ति से पहले सम्मिलित करने के लिए पाठ हैं, जिसे .अपनी पंक्ति में समाप्त किया गया है।

7

संभवतः कुछ भी अंतर्निहित नहीं है, लेकिन आप इस तरह से अपने खुद के बहुत आसानी से लिख सकते हैं:

#!/bin/bash
echo -n "$1" > /tmp/tmpfile.$$
cat "$2" >> /tmp/tmpfile.$$
mv /tmp/tmpfile.$$ "$2"

कम से कम ऐसा कुछ ...


6
अस्थायी फ़ाइल नाम के हिस्से के रूप में $ $ (वर्तमान पीआईडी) का उपयोग करने के लिए +1। यदि सामान्य उपयोग के लिए स्क्रिप्ट बनाते हैं, तो यह एक ही समय में एक ही स्क्रिप्ट चलाकर किसी अन्य उपयोगकर्ता को अस्थायी फ़ाइल को अधिलेखित करने से रोक देगा।
ई ब्राउन

3
उपयोग करना $$उत्पादन कोड के लिए अपर्याप्त है, हालांकि (Google सिमलिंक अटैक); लेकिन यह निश्चित रूप से एक स्थिर फ़ाइल नाम से बेहतर है।
ट्रिपलआई

1
बस का उपयोग करेंmktemp
Mewa

7

कुछ परिस्थितियों में पहले से तैयार पाठ केवल स्टड से उपलब्ध हो सकता है। तब यह संयोजन काम करेगा।

echo "to be prepended" | cat - text.txt | tee text.txt

यदि आप teeआउटपुट को छोड़ना चाहते हैं , तो संलग्न करें > /dev/null


मुझे वास्तव में यह उत्तर पसंद है। यह एक बहुत साफ और स्पष्ट तरीका है। टी का उपयोग इनपुट फ़ाइल में कैट आउटपुट के लिए प्रयास करने की समस्या का एक प्राकृतिक समाधान है। नाम बदलने के साथ भी कोई हैक नहीं। अभी उच्चतम मतदान समाधान से बेहतर है, क्योंकि यह एक नई फ़ाइल नहीं बनाता है। यह मूल रूप से निकटतम है जो आपको संलग्न करने के बजाय प्रीपेंडिंग के लिए >> के लिए मिलेगा।
DC2

यह अब तक का सबसे अच्छा और साफ जवाब है।
nerdoc

6
क्या कोई गारंटी है कि इसे पढ़ने से पहले teeक्लोबर नहीं करता है? मुझे नहीं लगता - जो इस समाधान को फ़ाइल के स्वास्थ्य के लिए खतरनाक बना देगा। text.txtcat
जोनाथन लेफ्लर

3
@JonathanLeffler शायद नहीं। मैंने परीक्षण करने के लिए इस कोड की कोशिश की lenA=1000000; yes a | head -c $lenA > a.txt; lenB=10000; b=$(yes b | head -c $lenB); echo "$b" | cat - a.txt | tee a.txt > /dev/null:। यदि lenA1000000 (1Mb फ़ाइल) है और lenB10000 (10Kb टेक्स्ट प्रीपेंड) है, तो "a.txt" फ़ाइल को "b" अक्षर के 20Kb के साथ ओवरराइट किया गया है। यह पूरी तरह से टूट गया है। अब, यदि आप प्रीपेन्ड करने के लिए 1Mb a.txt और 1Mb टेक्स्ट का उपयोग करते हैं, तो tee7Gb + फाइल बनाने वाले लूप में जाता है, मुझे कमांड को रोकना पड़ा। इसलिए, यह स्पष्ट है कि परिणाम बड़े आकारों के लिए अप्रत्याशित है। मुझे इस बात की कोई जानकारी नहीं है कि इसे छोटे आकारों पर काम करना चाहिए या नहीं।
वासिलीनोविकोव

3
इसे वैचारिक शब्दों में कहें: यह कमांड डेटा हानि में परिणाम देगा यदि इनपुट फ़ाइल आपके सिस्टम के पाइपलाइन बफर आकार से बड़ी होती है , जो आजकल 64 KB है।
mklement0

7

उपाय:

printf '%s\n%s' 'text to prepend' "$(cat file.txt)" > file.txt

ध्यान दें कि यह सभी प्रकार के इनपुट पर सुरक्षित है, क्योंकि कोई विस्तार नहीं है। उदाहरण के लिए, यदि आप पहले से !@#$%^&*()ugly text\n\t\nकाम करना चाहते हैं, तो यह काम करेगा:

printf '%s\n%s' '!@#$%^&*()ugly text\n\t\n' "$(cat file.txt)" > file.txt

अंतिम भाग विचार के लिए छोड़ दिया गया है कमांड प्रतिस्थापन के दौरान फ़ाइल के अंत में व्हाट्सएप हटाने "$(cat file.txt)"। इसके लिए सभी कार्य-क्षेत्र अपेक्षाकृत जटिल हैं। यदि आप file.txt के अंत में newlines संरक्षित करना चाहते हैं, तो इसे देखें: https://stackoverflow.com/a/22607352/1091436


इसे प्यार करना। सुपर पोर्टेबल और एक नई फ़ाइल उत्पन्न करने की आवश्यकता नहीं है। धन्यवाद!
pyb

1
इसके साथ एकमात्र समस्या यह आती है कि file.txtक्या इससे अधिक की सामग्री को तर्क सूची में फिट किया जा सकता है printf
जोनाथन लेफ़लर

6

उपयोग करने का दूसरा तरीका sed:

sed -i.old '1 {i to be prepended
}' inFile

यदि लाइन को पूर्व-निर्धारित किया जाना है, तो बहुस्तरीय है:

sed -i.old '1 {i\ 
to be prepended\
multiline
}' inFile

क्यों नहीं sed -i '1ito be prepended' inFile- या यह केवल GNU sed के लिए अनुमति है?
उपयोगकर्ता अज्ञात

@userunknown: मानक में sed, iकमांड के बाद एक बैकस्लैश और एक न्यूलाइन होता है, और इनपुट की प्रत्येक पंक्ति को अंतिम सिवाय एक बैकस्लैश के साथ भी समाप्त होता है। GNU आपके द्वारा sedपूछी गई लाइनों के साथ शॉर्टहैंड की अनुमति देता है, लेकिन यह केवल GNU है sedजो ऐसा करता है। '
जोनाथन लेफ़लर

3

जैसा कि बैश (उबंटू में) में परीक्षण किया गया है, यदि परीक्षण फ़ाइल के माध्यम से शुरू होता है;

echo "Original Line" > test_file.txt

आप निष्पादित कर सकते हैं;

echo "$(echo "New Line"; cat test_file.txt)" > test_file.txt

या, अगर बाश का संस्करण $ () के लिए बहुत पुराना है, तो आप बैकटिक्स का उपयोग कर सकते हैं;

echo "`echo "New Line"; cat test_file.txt`" > test_file.txt

और "test_file.txt" की निम्नलिखित सामग्री प्राप्त करें;

New Line
Original Line

कोई मध्यस्थ फ़ाइल, बस बैश / गूंज।


2
सबसे अच्छा उत्तर, मैंने इस उत्तर का उपयोग करके अपनी फ़ाइल को घुमाने के लिए यह एक-लाइनर लिखा: i for $ (<file2.txt); गूंज "$ (गूंज $ i; बिल्ली file.txt)"> file.txt; किया हुआ;
औरंगजेब

2

एक और काफी सीधे आगे समाधान है:

    $ echo -e "string\n" $(cat file)

यह मेरे लिए काम किया ... बस एक मामूली संशोधन, इनपुट फ़ाइल से बहुस्तरीय बनाए रखने के लिए आप इसे कुछ इस तरह से उद्धरणों में लपेटेंगे: इको-"string \ n" "$ (cat ~ / file.txt) "> ~ / file.txt;
क्रेग वेन

2
catदोहरे उद्धरण चिह्नों में पैरामीटर विस्तार नहीं होना एक डाउनवोट के लिए एक बहुत अच्छा कारण है । यह कोड फ़ाइल की सामग्रियों को शब्दों में विभाजित कर रहा है, और उनमें से प्रत्येक शब्द को एक अलग तर्क के रूप में पारित कर रहा है echo। आप मूल तर्क सीमाओं को खो देते हैं, आप नई अंक / टैब / आदि खो देते हैं, और मूल पाठ की तरह \tऔर तार \nको टैब और नए के साथ बदल दिया जाता है जैसे कि वे थे।
चार्ल्स डॉफी


0
# create a file with content..
echo foo > /tmp/foo
# prepend a line containing "jim" to the file
sed -i "1s/^/jim\n/" /tmp/foo
# verify the content of the file has the new line prepened to it
cat /tmp/foo

0

मैं एक फ़ंक्शन को परिभाषित करने और फिर आयात करने और जहां आवश्यक हो, का उपयोग करने की सलाह देता हूं।

prepend_to_file() { 
    file=$1
    text=$2

    if ! [[ -f $file ]] then
        touch $file
    fi

    echo "$text" | cat - $file > $file.new

    mv -f $file.new $file
}

फिर इसे इस तरह उपयोग करें:

prepend_to_file test.txt "This is first"
prepend_to_file test.txt "This is second"

आपकी फ़ाइल सामग्री तब होगी:

This is second
This is first

मैं परिवर्तन लॉग अपडेटर को लागू करने के लिए इस दृष्टिकोण का उपयोग करने वाला हूं।

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