यह शायद एक जटिल समाधान है ।
मैं ">>" जैसे एक साधारण ऑपरेटर की तलाश कर रहा हूं, लेकिन पहले से तैयार होने के लिए।
मुझे डर है कि यह मौजूद नहीं है। मुझे कुछ ऐसा करना होगा
एमवी मायफाइल टीएमपी cat myheader tmp> myfile
कुछ होशियार?
यह शायद एक जटिल समाधान है ।
मैं ">>" जैसे एक साधारण ऑपरेटर की तलाश कर रहा हूं, लेकिन पहले से तैयार होने के लिए।
मुझे डर है कि यह मौजूद नहीं है। मुझे कुछ ऐसा करना होगा
एमवी मायफाइल टीएमपी cat myheader tmp> myfile
कुछ होशियार?
जवाबों:
हैक नीचे एक त्वरित ऑफ-द-कफ जवाब जो काम किया है और प्राप्त upvotes के बहुत सारे थे। फिर, जैसा कि यह सवाल अधिक लोकप्रिय हो गया और अधिक समय बीत गया, नाराज लोगों ने यह रिपोर्ट करना शुरू कर दिया कि यह काम करता है लेकिन अजीब चीजें हो सकती हैं, या यह सिर्फ काम नहीं करता है, इसलिए इसे एक समय के लिए खराब कर दिया गया था। ऐसा मज़ा।
समाधान आपके सिस्टम पर फ़ाइल डिस्क्रिप्टर के सटीक कार्यान्वयन का शोषण करता है और, क्योंकि कार्यान्वयन निक्स के बीच महत्वपूर्ण रूप से भिन्न होता है, यह सफलता पूरी तरह से सिस्टम पर निर्भर है, निश्चित रूप से गैर-पोर्टेबल है, और किसी भी चीज़ के लिए भी निर्भर नहीं होना चाहिए।
अब, उस उत्तर के सभी के साथ:
फ़ाइल के लिए एक और फाइल डिस्क्रिप्टर बनाना ( exec 3<> yourfile
) थेंस राइटिंग टू ( >&3
) एक ही फाइल दुविधा पर पढ़ने / लिखने पर काबू पाने के लिए लगता है। 600k फ़ाइलों पर मेरे लिए awk के साथ काम करता है। हालाँकि 'कैट' का उपयोग करके एक ही चाल की कोशिश करना विफल हो जाता है।
प्रीपेन्डेज को एक चर के रूप में जागृत करना ( -v TEXT="$text"
) शाब्दिक उद्धरण समस्या को खत्म करता है जो इस ट्रिक को 'सेड' करने से रोकता है।
#!/bin/bash
text="Hello world
What's up?"
exec 3<> yourfile && awk -v TEXT="$text" 'BEGIN {print TEXT}{print}' yourfile >&3
यह अभी भी एक अस्थायी फ़ाइल का उपयोग करता है, लेकिन कम से कम यह एक पंक्ति में है:
echo "text" | cat - yourfile > /tmp/out && mv /tmp/out yourfile
-
के बाद cat
?
echo -n "text"
yourfile
एक सिम्लिंक है तो यह वह नहीं करेगा जो आप चाहते हैं।
echo '0a
your text here
.
w' | ed some_file
एड मानक संपादक है! http://www.gnu.org/fun/jokes/ed.msg.html
0r header.file
echo -e '0a\nyour text here\n.\nw' | ed some_file
जॉन मी: आपकी विधि को काम करने की गारंटी नहीं है, और शायद आप असफल हो जाएंगे यदि आप 4096 से अधिक बाइट सामान (कम से कम यही होता है कि गनु अवेक के साथ होता है, लेकिन मुझे लगता है कि अन्य कार्यान्वयन समान अवरोध होंगे)। न केवल यह उस स्थिति में विफल हो जाएगा, लेकिन यह एक अंतहीन लूप में प्रवेश करेगा जहां यह अपना स्वयं का आउटपुट पढ़ेगा, जिससे फ़ाइल उपलब्ध हो जाएगी जब तक कि सभी उपलब्ध स्थान भर न जाए।
इसे अपने लिए आजमाएँ:
exec 3<>myfile && awk 'BEGIN{for(i=1;i<=1100;i++)print i}{print}' myfile >&3
(चेतावनी: इसे थोड़ी देर बाद मार दें या यह फाइलसिस्टम को भर देगा)
इसके अलावा, इस तरह से फ़ाइलों को संपादित करना बहुत खतरनाक है, और यह बहुत बुरी सलाह है, जैसे कि कुछ तब होता है जब फ़ाइल को संपादित किया जा रहा है (क्रैश, डिस्क पूर्ण) आप लगभग असंगत स्थिति में फ़ाइल के साथ छोड़ दिए जाने की गारंटी देते हैं।
एक अस्थायी फ़ाइल के बिना संभव नहीं है, लेकिन यहां एक ऑनलाइनर जाता है
{ echo foo; cat oldfile; } > newfile && mv newfile oldfile
आप इसे अस्थायी फ़ाइलों के बिना अन्य साधनों जैसे कि एड या पर्ल का उपयोग कर सकते हैं।
यह ध्यान देने योग्य हो सकता है कि अक्सर यह एक अच्छा विचार है कि अस्थायी रूप से एक फ़ाइल का उपयोग कर सुरक्षित रूप से मटकेप जैसी उपयोगिता का उपयोग करके उत्पन्न किया जा सकता है, कम से कम यदि स्क्रिप्ट कभी रूट विशेषाधिकारों के साथ निष्पादित की जाएगी। आप उदाहरण के लिए निम्नलिखित (bash में फिर से) कर सकते हैं:
(tmpfile=`mktemp` && { echo "prepended text" | cat - yourfile > $tmpfile && mv $tmpfile yourfile; } )
यदि आपको अपने द्वारा नियंत्रित किए जाने वाले कंप्यूटर पर इसकी आवश्यकता है, तो पैकेज को "अधिक" स्थापित करें और "स्पंज" का उपयोग करें। तो आप कर सकते हैं:
cat header myfile | sponge myfile
{ echo "prepended text"; cat myfile } | sponge myfile
Bash heredoc का उपयोग करके आप tmp फ़ाइल की आवश्यकता से बच सकते हैं:
cat <<-EOF > myfile
$(echo this is prepended)
$(cat myfile)
EOF
यह काम करता है क्योंकि $ (कैट मायफाइल) का मूल्यांकन तब किया जाता है जब बैश स्क्रिप्ट का मूल्यांकन किया जाता है, इससे पहले कि बिल्ली को पुनर्निर्देशित किया जाए।
यह मानते हुए कि जिस फ़ाइल को आप संपादित करना चाहते हैं वह my.txt है
$cat my.txt
this is the regular file
और जिस फाइल को आप प्रेप करना चाहते हैं वह हैडर
$ cat header
this is the header
हेडर फ़ाइल में एक अंतिम रिक्त पंक्ति होना सुनिश्चित करें।
अब आप इसे पहले से तैयार कर सकते हैं
$cat header <(cat my.txt) > my.txt
आप के साथ अंत
$ cat my.txt
this is the header
this is the regular file
जहाँ तक मुझे पता है यह केवल 'बाश' में काम करता है।
this is the header
my.txt की दो पंक्तियों के साथ समाप्त किया । मेरे द्वारा बैश को अपडेट करने के बाद भी मुझे 4.3.42(1)-release
वही परिणाम मिलता है।
<(...)
) में कमांड लिखता है, इसलिए कोई गारंटी नहीं है कि my.txt
पूर्ण अप फ्रंट में पढ़ा जाता है , जिसके बिना यह तकनीक काम नहीं करेगी।
जब आप उन चीजों को करने की कोशिश करने लगते हैं जो शेल-स्क्रिप्ट में कठिन हो जाती हैं, तो मैं दृढ़ता से स्क्रिप्ट को "उचित" स्क्रिप्टिंग भाषा (पायथन / पर्ल / रूबी / आदि) में पुन: लिखने का सुझाव दूंगा।
किसी फ़ाइल में किसी पंक्ति को प्रस्तुत करने के लिए, पाइपिंग के माध्यम से ऐसा करना संभव नहीं है, जब आप कुछ भी ऐसा करते हैं cat blah.txt | grep something > blah.txt
, तो यह अनजाने में फ़ाइल को खाली कर देता है। एक छोटी उपयोगिता कमांड है जिसे sponge
आप इंस्टॉल कर सकते हैं (आप करते हैं cat blah.txt | grep something | sponge blah.txt
और यह फ़ाइल की सामग्री को बफ़र करता है, फिर इसे फ़ाइल पर लिखता है)। यह एक अस्थायी फ़ाइल के समान है लेकिन आपको स्पष्ट रूप से ऐसा नहीं करना है। लेकिन मैं कहूंगा कि पर्ल की तुलना में यह "बदतर" आवश्यकता है।
हो सकता है कि इसे awk या समान के माध्यम से करने का कोई तरीका हो, लेकिन यदि आपको शेल-स्क्रिप्ट का उपयोग करना है, तो मुझे लगता है कि एक अस्थायी फ़ाइल अब तक का सबसे आसान (/?) तरीका है ..?
जैसे डैनियल वेलकोव सुझाव देते हैं, टी का उपयोग करें।
मेरे लिए, यह आसान स्मार्ट समाधान है:
{ echo foo; cat bar; } | tee bar > /dev/null
संपादित करें: यह टूट गया है। बिल्ली और टी के साथ एक फ़ाइल को प्रस्तुत करते समय अजीब व्यवहार देखें
समस्या को अधिलेखित करने के लिए समाधान का उपयोग कर रहा है tee
:
cat header main | tee main > /dev/null
वह जो मैं उपयोग करता हूं। यह आपको आदेश, अतिरिक्त वर्ण इत्यादि को निर्दिष्ट करने की अनुमति देता है जिस तरह से आप इसे पसंद करते हैं:
echo -e "TEXTFIRSt\n$(< header)\n$(< my.txt)" > my.txt
पुनश्च: केवल यह काम नहीं कर रहा है यदि फ़ाइलों में बैकस्लैश के साथ पाठ होता है, क्योंकि यह व्याख्या वर्णों के रूप में हो जाता है
ज्यादातर मौज-मस्ती / शेल गोल्फ के लिए, लेकिन
ex -c '0r myheader|x' myfile
चाल करेंगे, और कोई पाइपलाइन या पुनर्निर्देशन नहीं हैं। बेशक, vi / ex वास्तव में गैर-उपयोग के लिए नहीं है, इसलिए vi संक्षेप में फ़्लैश होगा।
केवल एड कमांड का उपयोग क्यों नहीं किया जाता (जैसा कि पहले से ही यहाँ फ़्लफ़ल द्वारा सुझाया गया है)?
ed पूरी फ़ाइल को मेमोरी में पढ़ता है और स्वचालित रूप से एक इन-प्लेस फ़ाइल एडिट करता है!
इसलिए, यदि आपकी फ़ाइल इतनी बड़ी नहीं है ...
# cf. "Editing files with the ed text editor from scripts.",
# http://wiki.bash-hackers.org/doku.php?id=howto:edit-ed
prepend() {
printf '%s\n' H 1i "${1}" . wq | ed -s "${2}"
}
echo 'Hello, world!' > myfile
prepend 'line to prepend' myfile
फिर भी एक और समाधान खुले फ़ाइल हैंडल का उपयोग करना होगा जैसा कि sed के s / c / d / 'myFile से Redirect आउटपुट में Jürgen Hötzel द्वारा सुझाया गया है।
echo cat > manipulate.txt
exec 3<manipulate.txt
# Prevent open file from being truncated:
rm manipulate.txt
sed 's/cat/dog/' <&3 > manipulate.txt
यह सब निश्चित रूप से एक ही लाइन पर रखा जा सकता है।
निश्चित पाठ को प्रस्तुत करने के लिए "नो टेम्प फाइल" के cb0 के समाधान पर एक संस्करण:
echo "text to prepend" | cat - file_to_be_modified | ( cat > file_to_be_modified )
फिर से यह सब-शेल के निष्पादन पर निर्भर करता है - (..) - बिल्ली से बचने के लिए इनपुट और आउटपुट के लिए एक ही फाइल होने से इंकार करना।
नोट: यह समाधान पसंद आया। हालांकि, मेरे मैक में मूल फ़ाइल खो गई है (सोचा कि यह नहीं होना चाहिए लेकिन यह करता है)। आपके समाधान को इस रूप में लिखकर तय किया जा सकता है: गूंज "पाठ को प्रस्तुत करने के लिए" | cat - file_to_be_modified | cat> tmp_file; mv tmp_file file_to_be_modified
यहाँ मैंने क्या पाया:
echo -e "header \n$(cat file)" >file
चेतावनी: यह ओपी की जरूरतों को पूरा करने के लिए थोड़ा और काम करने की जरूरत है।
उनकी गलतफहमियों के बावजूद @shixilun काम करके सेड अप्रोच बनाने का एक तरीका होना चाहिए। व्हाट्सएप से बचने के लिए एक बैश कमांड होना चाहिए जब किसी फाइल को एक सेड विकल्प स्ट्रिंग में पढ़ा जाए (जैसे कि newline वर्णों को '\ n' से बदलें। शेल कमांड vis
और cat
नॉनप्रिंटेबल कैरेक्टर से निपट सकते हैं, लेकिन व्हाट्सएप से नहीं, इसलिए यह ओपी को हल नहीं करेगा। संकट:
sed -i -e "1s/^/$(cat file_with_header.txt)/" file_to_be_prepended.txt
स्थानापन्न स्क्रिप्ट में कच्चे newlines के कारण विफल रहता है, जिसे एक पंक्ति निरंतरता चरित्र () के साथ पहले से तैयार करने की आवश्यकता होती है और संभवतः एक के बाद एक शेल और sed को खुश रखने के लिए, जैसे SO उत्तर।
sed
गैर-वैश्विक खोज-प्रतिस्थापित आदेशों (पैटर्न के बाद कोई अनुगामी / छ) के लिए 40K की आकार सीमा होती है, इसलिए संभवतः उस अज्ञात चेतावनी के डरावने बफ़र ओवररन समस्याओं से बचना होगा।
sed -i -e "1s/^/new first line\n/" old_file.txt
इसके साथ एक समाधान printf
:
new_line='the line you want to add'
target_file='/file you/want to/write to'
printf "%s\n$(cat ${target_file})" "${new_line}" > "${target_file}"
आप भी कर सकते हैं:
printf "${new_line}\n$(cat ${target_file})" > "${target_file}"
लेकिन उस मामले में आपको यह सुनिश्चित करना होगा कि %
लक्ष्य फ़ाइल की सामग्री सहित कोई भी कहीं भी नहीं है , क्योंकि इसकी व्याख्या की जा सकती है और आपके परिणामों को खराब कर सकती है।
echo
एक सुरक्षित विकल्प की तरह लगता है। echo "my new line\n$(cat my/file.txt)" > my/file.txt
${new_line}
, नहीं लक्ष्य फ़ाइल
आप पर्ल कमांड लाइन का उपयोग कर सकते हैं:
perl -i -0777 -pe 's/^/my_header/' tmp
जहाँ-मैं फ़ाइल का इनलाइन रिप्लेसमेंट बनायेगा और -0777 पूरी फाइल को स्लैप करेगा और केवल शुरुआत से ^ मैच करेगा। -pe सभी लाइनों को प्रिंट करेगा
या अगर my_header एक फ़ाइल है:
perl -i -0777 -pe 's/^/`cat my_header`/e' tmp
जहां / ई प्रतिस्थापन में कोड का एक निकासी की अनुमति देगा।
मुझे @ fluffle का एड सबसे अच्छा आ रहा है। आखिरकार, किसी भी टूल की कमांड लाइन स्विच बनाम स्क्रिप्टेड एडिटर कमांड अनिवार्य रूप से एक ही चीज है; स्क्रिप्टेड एडिटर सॉल्यूशन "स्वच्छता" को किसी भी तरह से कम या व्हाट्सएप पर नहीं देखना।
यहां मेरा एक-लाइनर संदेश .git/hooks/prepare-commit-msg
भेजने के लिए इन-रेपो .gitmessage
फ़ाइल को प्रस्तुत करने के लिए संलग्न है :
echo -e "1r $PWD/.gitmessage\n.\nw" | ed -s "$1"
उदाहरण .gitmessage
:
# Commit message formatting samples:
# runlevels: boot +consolekit -zfs-fuse
#
मैं 1r
इसके बजाय कर रहा हूं 0r
, क्योंकि यह मूल टेम्पलेट से फ़ाइल के ऊपर खाली रेडी-टू-राइट लाइन को छोड़ देगा। अपने ऊपर एक खाली लाइन मत डालो .gitmessage
, तुम दो खाली लाइनों के साथ समाप्त हो जाओगे। -s
एड के नैदानिक जानकारी आउटपुट को दबा देता है।
इसके माध्यम से जाने के संबंध में, मुझे पता चला कि विम-बफ के लिए भी अच्छा है:
[core]
editor = vim -c ':normal gg'
यदि आप BASH में स्क्रिप्टिंग कर रहे हैं, वास्तव में, आप बस जारी कर सकते हैं:
बिल्ली - yourfile / tmp / out && mv / tmp / out yourfile
यह वास्तव में कॉम्प्लेक्स उदाहरण में है जिसे आप स्वयं अपने प्रश्न में पोस्ट करते हैं।
cat - yourfile <<<"text" > /tmp/out && mv /tmp/out yourfile
, हालांकि यह मेरे उत्तर से पर्याप्त रूप से भिन्न है कि यह स्वयं का उत्तर होना चाहिए।
IMHO कोई खोल समाधान है (और कभी नहीं होगा) कि लगातार और मज़बूती से जो कुछ भी दो फ़ाइलों के आकार काम करेगा myheader
और myfile
। इसका कारण यह है कि यदि आप ऐसा करना चाहते हैं, तो बिना किसी अस्थायी फ़ाइल में आए (और शेल को चुपचाप अस्थायी फ़ाइल में जाने के बिना, जैसे निर्माण के माध्यम से exec 3<>myfile
, पाइपिंग से tee
, आदि)।
"वास्तविक" समाधान जिसे आप फाइल सिस्टम के साथ फील करना चाहते हैं, और इसलिए यह यूजर्सस्पेस में उपलब्ध नहीं है और प्लेटफॉर्म-डिपेंडेंट होगा: आप फाइल सिस्टम पॉइंटर myfile
के वर्तमान मान से उपयोग में फाइलसिस्टम पॉइंटर को संशोधित करने के लिए कह रहे हैं। के लिए myheader
और फाइल सिस्टम में की जगह EOF
के myheader
द्वारा बताया वर्तमान फाइल सिस्टम का पता करने के लिए एक श्रृंखलित लिंक के साथ myfile
। यह तुच्छ नहीं है और स्पष्ट रूप से एक गैर-सुपरयुसर द्वारा नहीं किया जा सकता है, और शायद सुपरयूजर द्वारा भी नहीं किया जा सकता है ... इनोड्स के साथ खेलें, आदि।
यद्यपि आप लूप डिवाइस का उपयोग करके इसे कम या ज्यादा नकली बना सकते हैं। उदाहरण के लिए यह SO थ्रेड देखें ।
mktemp
? आप हमेशा अस्थायी फ़ाइल को बाद में साफ कर सकते हैं ...