কোনও ফাইলের শেষে কীভাবে একটি নতুন লাইন যুক্ত করবেন?


190

সংস্করণ নিয়ন্ত্রণ ব্যবস্থা ব্যবহার করে আমি যখন ডফফ বলি তখন আমি শব্দে বিরক্ত হই No newline at end of file

তাই আমি ভাবছিলাম: এই বার্তাগুলি থেকে মুক্তি পেতে কোনও ফাইলের শেষে কীভাবে একটি নিউলাইন যুক্ত করবেন?



1
নীচের সুন্দর সমাধানটি যা সমস্ত ফাইলকে পুনরাবৃত্তভাবে স্যানিটাইজ করে। @Patrick Oscity দ্বারা উত্তর
কোয়ার্টি


এগিয়ে যেতে, পাঠ্য সম্পাদকদের প্রায়শই বিকল্পগুলি থাকে যাতে আপনি এবং আপনার সহযোগীরা পরিচ্ছন্ন রাখতে ব্যবহার করতে পারেন এমন একটি অনুচরিত নতুন লাইন রয়েছে ensure
নিক টি

উত্তর:


44

কোনও প্রকল্প পুনরাবৃত্তভাবে স্যানিটাইজ করার জন্য আমি এই অনলাইনারটি ব্যবহার করি:

git ls-files -z | while IFS= read -rd '' f; do tail -c1 < "$f" | read -r _ || echo >> "$f"; done

ব্যাখ্যা:

  • git ls-files -zসংগ্রহস্থলে ফাইল তালিকাভুক্ত করে। অতিরিক্ত প্যারামিটার হিসাবে এটি একটি .চ্ছিক প্যাটার্ন নেয় যা আপনি যদি কিছু ফাইল / ডিরেক্টরিতে অপারেশন সীমাবদ্ধ রাখতে চান তবে কিছু ক্ষেত্রে কার্যকর হতে পারে। বিকল্প হিসাবে, আপনি find -print0 ...প্রভাবিত ফাইলগুলির তালিকা করতে বা অনুরূপ প্রোগ্রামগুলি ব্যবহার করতে পারেন - এটি নিশ্চিত করুন - এটি NULস্বীকৃত এন্ট্রিগুলি নির্গত করে ।

  • while IFS= read -rd '' f; do ... done এন্ট্রিগুলির মাধ্যমে পুনরাবৃত্তি করে, নিরাপদে হোয়াইটস্পেস এবং / অথবা নিউলাইন অন্তর্ভুক্ত ফাইলের নামগুলি পরিচালনা করে।

  • tail -c1 < "$f" একটি ফাইল থেকে শেষ চর পড়ে।

  • read -r _ যদি একটি নতুন ট্রেইলিং অনুপস্থিত থাকে তবে ননজারো প্রস্থান স্থিতির সাথে প্রস্থান করে।

  • || echo >> "$f" পূর্ববর্তী কমান্ডের প্রস্থান স্থিতি যদি নাজারো হয় তবে ফাইলটিতে একটি নতুন লাইন যুক্ত হয়।


আপনি যদি কেবল নিজের ফাইলগুলির একটি উপসেট স্যানিটাইজ করতে চান তবে আপনি এটিও এটি করতে পারেন:find -name \*.java | while read f; do tail -n1 $f | read -r _ || echo >> $f; done
প্রতি লন্ডবার্গ

@ স্টাফেনচেজেলাস ভাল পরামর্শ, এটিকে আমার উত্তরে অন্তর্ভুক্ত করার চেষ্টা করবে।
প্যাট্রিক অসিটি

@ পেরলুন্ডবার্গ আপনি এমন একটি প্যাটার্নও পাস করতে পারেন git ls-filesযা এখনও সংস্করণ নিয়ন্ত্রণে ট্র্যাক করা হয়নি এমন ফাইলগুলি সম্পাদনা করা থেকে রক্ষা করবে।
প্যাট্রিক অসিটি

@ স্টাফেনচাজেলাস বিভাজনকারীকে IFS= আনসেট করতে যোগ করা আশেপাশের শ্বেতস্থান সংরক্ষণ করা ভাল। নাল টার্মিনেটেড এন্ট্রিগুলি কেবলমাত্র তখনই প্রাসঙ্গিক যে আপনার নামে একটি নতুন লাইন যুক্ত ফাইল বা ডিরেক্টরি রয়েছে, যা এক ধরণের প্রকারের মনে হয় তবে জেনেরিক কেস পরিচালনা করার আরও সঠিক উপায়, আমি সম্মত। শুধু একটি ছোট সতর্কীকরণ হিসাবে: -dবিকল্পে readPOSIX SH উপলব্ধ নেই।
প্যাট্রিক অসিটি

হ্যাঁ, তাই আমার zsh / বাশ এরtail -n1 < "$f"ফাইল নামের সাথে সমস্যাগুলি এড়ানোর জন্য আমার ব্যবহারটি দেখুন যা দিয়ে শুরু হয় -(কল করা tail -n1 -- "$f"ফাইলটির জন্য কাজ করে না -)। আপনি পরিষ্কার করতে চাইতে পারেন যে উত্তরটি এখন zsh / বাশ নির্দিষ্ট।
স্টাফেন চেজেলাস

202

আপনি এখানে যান :

sed -i -e '$a\' file

এবং বিকল্পভাবে ওএস এক্স এর জন্য sed:

sed -i '' -e '$a\' file

এটি কেবল\n ফাইলের শেষে যুক্ত হয় যদি এটি ইতিমধ্যে কোনও নতুন লাইন দিয়ে শেষ না হয়। সুতরাং আপনি যদি এটি দুটিবার চালনা করেন তবে এটি আর একটি নতুন লাইন যুক্ত করবে না:

$ cd "$(mktemp -d)"
$ printf foo > test.txt
$ sed -e '$a\' test.txt > test-with-eol.txt
$ diff test*
1c1
< foo
\ No newline at end of file
---
> foo
$ echo $?
1
$ sed -e '$a\' test-with-eol.txt > test-still-with-one-eol.txt
$ diff test-with-eol.txt test-still-with-one-eol.txt
$ echo $?
0

1
@jwd: থেকে man sed: $ Match the last line.তবে সম্ভবত এটি কেবল দুর্ঘটনাক্রমে কাজ করে। আপনার সমাধানটিও কাজ করে।
l0b0

1
আপনার সমাধানটি আরও মার্জিত এবং আমি এটি পরীক্ষা করেছি এবং প্রতিশ্রুতিবদ্ধ করেছি তবে এটি কীভাবে কাজ করতে পারে? যদি $শেষ লাইনের সাথে মিলে যায় তবে কেন এটি ইতিমধ্যে একটি নিউলাইন রয়েছে এমন স্ট্রিংয়ে অন্য একটি নতুন লাইন যুক্ত হবে না?
l0b0

27
এর দুটি পৃথক অর্থ রয়েছে $। একটি রেইজেক্সের অভ্যন্তরে যেমন ফর্মের সাথে /<regex>/এটির সাথে "লাইনের শেষ ম্যাচ" অর্থ রয়েছে। অন্যথায়, ঠিকানা হিসাবে ব্যবহৃত, সেড এটি বিশেষ "ফাইলের শেষ লাইন" অর্থ দেয়। কোডটি কাজ করে কারণ সেডটি ডিফল্টরূপে এর আউটপুটটিতে একটি নতুন লাইন যুক্ত করে যদি এটি ইতিমধ্যে না থাকে। "$ A \" কোডটি কেবল বলেছে "ফাইলের শেষ লাইনের সাথে মেলে এবং এতে কিছুই জুড়বে না।" তবে স্পষ্টতই, সেড প্রতিটি লাইনে প্রসেস করে নতুন লাইন যুক্ত করে (যেমন এই $লাইন) যদি এটি ইতিমধ্যে না থাকে তবে।
jwd

1
মানচিত্রটি সম্পর্কে: আপনি যে উদ্ধৃতিটি উল্লেখ করছেন সেটি "ঠিকানাগুলি" বিভাগের অধীনে। এটি ভিতরে রাখা /regex/এটি একটি আলাদা অর্থ দেয়। ফ্রিবিএসডি ম্যানাপেজগুলি
jwd

2
যদি ফাইলটি ইতিমধ্যে একটি নতুন লাইনে শেষ হয় তবে এটি এটি পরিবর্তন করে না, তবে এটি এটি আবার লিখতে এবং এর টাইমস্ট্যাম্পটি আপডেট করে। সেটা হতে পারে বা নাও পারে।
কিথ থম্পসন

39

একবার দেখুন:

$ echo -n foo > foo 
$ cat foo
foo$
$ echo "" >> foo
$ cat foo
foo

সুতরাং echo "" >> noeol-fileকৌশলটি করা উচিত। (বা আপনার অর্থ এই ফাইলগুলি সনাক্তকরণ এবং সেগুলি ঠিক করার জন্য জিজ্ঞাসা করার অর্থ ছিল ?)

সম্পাদনা এতে ""থেকে সরানো হয়েছে echo "" >> foo(@ ইয়ুইচাওর মন্তব্য দেখুন) edit2"" আবার যুক্ত করেছে ( তবে @ কিথ থম্পসনের মন্তব্য দেখুন)


4
""প্রয়োজনীয় (অন্তত ব্যাশ জন্য) নয় এবং tail -1 | wc -lশেষে একটি নতুন লাইন ছাড়া ফাইল খুঁজে বের করতে ব্যবহার করা যেতে পারে
yuyichao

5
@ ইউয়াইচাও: বাশের ""জন্য এটি প্রয়োজনীয় নয়, তবে আমি এমন echoবাস্তবায়ন দেখেছি যেগুলি যুক্তি ছাড়াই আহ্বান করা হলে কিছুই মুদ্রিত হয় না (যদিও এখন যেগুলির মধ্যে আমি খুঁজে পেতে পারি তার কোনওটিই এটি করে না)। echo "" >> noeol-fileসম্ভবত কিছুটা বেশি শক্তিশালী। printf "\n" >> noeol-fileআরও বেশি তাই।
কিথ থম্পসন

2
@KeithThompson, cshএর echoআউটপুট কিছুই পরিচিত যখন কোনো আর্গুমেন্ট পাস না হয়। কিন্তু তারপর যদি আমরা অ বোর্ন মত শাঁস সমর্থন করার জন্য চলুন, আমরা এটা করা উচিত echo ''পরিবর্তে echo ""যেমন echo ""ouput হবে ""<newline>সঙ্গে rcবা esউদাহরণস্বরূপ।
স্টাফেন চেজেলাস

1
@ স্টাফেনচাজেলাস: এবং এর tcshবিপরীতে csh, কোনও বিন্যাস ছাড়াই অনুরোধ করা হলে একটি নিউলাইন প্রিন্ট করে - সেটিং নির্বিশেষে $echo_style
কিথ থম্পসন

16

আর একটি সমাধান ব্যবহার করে ed। এই সমাধানটি কেবলমাত্র সর্বশেষ লাইনে প্রভাব ফেলবে এবং কেবল \nঅনুপস্থিত থাকলে:

ed -s file <<< w

এটি মূলত কোনও স্ক্রিপ্টের মাধ্যমে সম্পাদনা করার জন্য ফাইলটি খোলার কাজ করে, স্ক্রিপ্টটি একক wকমান্ড, যা ফাইলটি ডিস্কে ফিরে লেখেন। এটি ed(1)ম্যান পেজে পাওয়া এই বাক্যটির ভিত্তিতে :

সীমাবদ্ধতা
       (...)

       যদি কোনও পাঠ্য (নন-বাইনারি) ফাইলটি একটি নতুন লাইন অক্ষর দ্বারা শেষ না করা হয়,
       তারপরে এড পড়ার / লেখার ক্ষেত্রে এটিকে যুক্ত করে। বাইনারি ক্ষেত্রে
       ফাইল, এড পড়া / লেখার ক্ষেত্রে একটি নতুন লাইন যুক্ত করে না।

1
এটি আমার জন্য একটি নতুন লাইন যুক্ত করে না।
ওলোভস্কি

4
আমার জন্য কাজ কর; এমনকি এটি "নিউলাইন সংযুক্ত" (আর্ট লিনাক্স-এ -১.১০-১) প্রিন্ট করে।
স্টিফান মাজেউস্কি

12

কোনও অনুপস্থিত, চূড়ান্ত নিউলাইনটি একটিতে যুক্ত করার জন্য একটি সহজ, পোর্টেবল, পসিএক্স-সম্মতিযুক্ত উপায় হ'ল পাঠ্য ফাইল হবে:

[ -n "$(tail -c1 file)" ] && echo >> file

এই পদ্ধতির পুরো ফাইলটি পড়ার দরকার নেই; এটি কেবল ইওএফের সন্ধান করতে এবং সেখান থেকে কাজ করতে পারে।

এই পদ্ধতির জন্য আপনার পিছনের পিছনে টেম্প ফাইলগুলি তৈরি করার দরকার নেই (যেমন সেড-আই), তাই হার্ডলিঙ্কগুলি প্রভাবিত হয় না।

প্রতিধ্বনি তখনই ফাইলটিতে একটি নতুন লাইন যুক্ত করে যখন কমান্ড প্রতিস্থাপনার ফলাফলটি একটি শূন্যস্থান না থাকে। দ্রষ্টব্য যে কেবলমাত্র যদি ফাইলটি খালি না থাকে এবং শেষ বাইটটি কোনও নতুন লাইন না হয় তবেই এটি ঘটতে পারে।

যদি ফাইলের শেষ বাইটটি একটি নতুন লাইন হয় তবে লেজ এটি ফিরিয়ে দেয়, তারপরে কমান্ড প্রতিস্থাপন এটি স্ট্রিপ করে; ফলাফলটি একটি খালি স্ট্রিং। -N পরীক্ষা ব্যর্থ হয় এবং প্রতিধ্বনি চলে না।

যদি ফাইলটি খালি থাকে, কমান্ড প্রতিস্থাপনের ফলাফলটিও একটি খালি স্ট্রিং, এবং আবার প্রতিধ্বনি চলবে না। এটি আকাঙ্খিত, কারণ একটি খালি ফাইলটি কোনও অবৈধ পাঠ্য ফাইল নয়, এটি খালি লাইন সহ একটি খালি খালি পাঠ্য ফাইলের সমান নয়।


1
নোট করুন যে yashফাইলের শেষ অক্ষরটি একটি বহু-বাইট অক্ষর (উদাহরণস্বরূপ ইউটিএফ -8 স্থানীয় অবস্থানে), বা যদি লোকেল সি এবং ফাইলের শেষ বাইটে 8 তম বিট সেট থাকে তবে এটি কাজ করে না। অন্যান্য শেলগুলির সাথে (zsh ব্যতীত) ফাইলটি কোনও NUL বাইটে শেষ হয়ে গেলে এটি কোনও নতুন লাইন যুক্ত করবে না (তবে তারপরে আবার, এর অর্থ হ'ল নতুন লাইন যুক্ত হওয়ার পরেও ইনপুটটি অ-পাঠ্য হবে)।
স্টাফেন চেজেলাস


1
ফোল্ডার এবং সাবফোল্ডারগুলির প্রতিটি ফাইলের জন্য এটি চালানো সম্ভব?
কিওয়ার্টি

12

নির্বিশেষে নতুন লাইন যুক্ত করুন:

echo >> filename

পাইথন ব্যবহার করে একটি যুক্ত করার আগে একটি নতুন লাইন শেষে উপস্থিত রয়েছে কিনা তা যাচাই করার জন্য এখানে একটি উপায়:

f=filename; python -c "import sys; sys.exit(open(\"$f\").read().endswith('\n'))" && echo >> $f

1
ধীর পাইথন শুরু হওয়ার কারণে আমি কোনও ধরণের লুপে পাইথন সংস্করণটি ব্যবহার করব না। আপনি চাইলে অবশ্যই অজগরটিতে লুপটি করতে পারতেন।
কেভিন কক্স

2
পাইথনের শুরু করার সময়টি এখানে 0.03 সেকেন্ড। আপনি কি সত্যিই সমস্যাযুক্ত হিসাবে বিবেচনা করেন?
আলেকজান্ডার

3
প্রারম্ভ সময় আপনি একটি লুপ পাইথন কল, তাই আমি বললাম লুপ করছেন বিবেচনা ব্যাপার মধ্যে পাইথন। তারপরে আপনি কেবল একবার স্টার্টআপ ব্যয় করতে পারেন। আমার জন্য, স্টার্টআপের অর্ধেক ব্যয় পুরো স্নিপিটের সময়ের অর্ধেকের বেশি, আমি সেই যথেষ্ট ওভারহেড বিবেচনা করব। (আবার, কেবলমাত্র অল্প সংখ্যক ফাইল করা অপ্রাসঙ্গিক)
কেভিন কক্স

2
echo ""তুলনায় আরো শক্তিশালী বলে মনে হচ্ছে echo -n '\n'। বা আপনি ব্যবহার করতে পারেনprintf '\n'
কিথ থমসন

2
এটি আমার পক্ষে ভাল কাজ করেছে
ড্যানিয়েল গোমেজ রিকো

8

দ্রুত সমাধানটি হ'ল:

[ -n "$(tail -c1 file)" ] && printf '\n' >>file 

  1. সত্যিই দ্রুত।
    মাঝারি আকারের ফাইলে seq 99999999 >fileএটি মিলিসেকেন্ড নেয়।
    অন্যান্য সমাধানগুলি দীর্ঘ সময় নেয়:

    [ -n "$(tail -c1 file)" ] && printf '\n' >>file  0.013 sec
    vi -ecwq file                                    2.544 sec
    paste file 1<> file                             31.943 sec
    ed -s file <<< w                             1m  4.422 sec
    sed -i -e '$a\' file                         3m 20.931 sec
    
  2. ছাই, বাশ, লক্ষ, মক্ষ, ksh93, আতশ এবং জেডে কাজ করে তবে যশ নয়।

  3. কোনও নতুন লাইন যুক্ত করার প্রয়োজন না থাকলে ফাইল টাইমস্ট্যাম্প পরিবর্তন করে না।
    এখানে উপস্থাপিত অন্যান্য সমস্ত সমাধান ফাইলের টাইমস্ট্যাম্প পরিবর্তন করে।
  4. উপরের সমস্ত সমাধান বৈধ POSIX।

আপনার যদি যশ (এবং উপরে তালিকাভুক্ত অন্যান্য সমস্ত শেল) পোর্টেবল সমাধানের প্রয়োজন হয় তবে এটি কিছুটা জটিল হতে পারে:

f=file
if       [ "$(tail -c1 "$f"; echo x)" != "$(printf '\nx')" ]
then     printf '\n' >>"$f"
fi

7

কোনও ফাইলের শেষ বাইটটি যদি নতুন লাইন হয় তা পরীক্ষা করার দ্রুততম উপায়টি কেবলমাত্র সেই শেষ বাইটটিই পড়তে হয়। এটি দিয়ে করা যেতে পারে tail -c1 file। যাইহোক, বাইট মানটি একটি নতুন লাইন কিনা তা পরীক্ষা করার সরল পদ্ধতিতে কমান্ড প্রসারণের অভ্যন্তরে অনুমান করা নতুন লাইনের শেলের উপর নির্ভর করে যশতে ব্যর্থ হয় (উদাহরণস্বরূপ), যখন ফাইলের শেষ অক্ষরটি ইউটিএফ- হয় 8 মান।

কোনও ফাইলের শেষ বাইটটি নতুন লাইন কিনা xxd বা hexdump ব্যবহারের জন্য সঠিক, পসিক্স-সম্মতিযুক্ত, সমস্ত (যুক্তিসঙ্গত) শাঁস উপায়:

tail -c1 file | xxd -u -p
tail -c1 file | hexdump -v -e '/1 "%02X"'

তারপরে, উপরের আউটপুটটির সাথে তুলনা করা 0Aএকটি শক্ত পরীক্ষা দেবে।
অন্যথায় খালি ফাইলটিতে একটি নতুন লাইন যুক্ত করা এড়াতে দরকারী is
ফাইল যা অবশ্যই একটি শেষ চরিত্র সরবরাহ করতে ব্যর্থ হবে 0A:

f=file
a=$(tail -c1 "$f" | hexdump -v -e '/1 "%02X"')
[ -s "$f" -a "$a" != "0A" ] && echo >> "$f"

স্বল্প ও মধুর. এটি কেবলমাত্র সর্বশেষ বাইটটি পড়ার কারণে খুব কম সময় নেয় (ইওফের দিকে তাকান)। ফাইলটি বড় হলে কিছু যায় আসে না। তারপরে প্রয়োজনে কেবল একটি বাইট যুক্ত করুন।

কোনও টেম্প ফাইলের প্রয়োজন নেই বা ব্যবহৃত হয়নি। কোনও হার্ডলিঙ্ক ক্ষতিগ্রস্থ হয় না।

যদি এই পরীক্ষাটি দু'বার চালানো হয় তবে এটি আর একটি নতুন লাইন যুক্ত করবে না


1
@ ক্রু আমি বিশ্বাস করি যে এটি দরকারী তথ্য যুক্ত করে।
sorontar

2
মনে রাখবেন যে, তন্ন তন্ন xxdনা hexdumpPOSIX ইউটিলিটি আছে। পসিক্স টুলকেষ্টে od -An -tx1বাইটের হেক্স মান পাওয়া যায়।
স্টাফেন চেজেলাস

@ স্টাফেনচাজেলাস দয়া করে উত্তর হিসাবে পোস্ট করুন; আমি এখানে অনেকবার এই মন্তব্যটি অনুসন্ধান করতে এসেছি :)
ক্যালভিন


নোট করুন যে পসিক্স এলএফের মান 0x0a হওয়ার গ্যারান্টি দেয় না। এখনও পসিক্স সিস্টেম রয়েছে যেখানে এটি নেই (ইবিসিডিক ভিত্তিক একটি) যদিও তারা এই দিনগুলিতে অত্যন্ত বিরল।
স্টাফেন চেজেলাস

4

আপনি সর্বশেষে ফাইলটি সম্পাদনা করেছেন এমন সম্পাদকের সংশোধন করা ভাল better আপনি যদি ফাইলটি সম্পাদনা করার শেষ ব্যক্তি হন - আপনি কোন সম্পাদকটি ব্যবহার করছেন, আমি অনুমান করছি পাঠ্যসেবক ..?


2
প্রশ্নটিতে সম্পাদক হলেন ভিম। তবে সাধারণভাবে, আপনি ঠিক বলেছেন, আমার কেবল লক্ষণগুলি ঠিক করা উচিত নয়;)
k0pernikus

6
তেজ, আপনি আপনার পথ থেকে সরে যান এবং বাইনারি ফাইল-অন-সংরক্ষণ তেজ পেতে থেকে নাচ করতে হবে না শুধু যে নাচ না - ফাইল শেষে একটি নতুন লাইন যোগ করুন। অথবা, বিদ্যমান ফাইলগুলি কেবলমাত্র ভিএম এ খুলুন এবং ফাইলটি সংরক্ষণ করুন এবং
ভিএম

3
emacsফাইলের শেষে আমার কোনও নতুন লাইন যুক্ত হবে না।
এনজোটিব

2
@ AD7six মন্তব্যের জন্য ধন্যবাদ, মূল ফাইলটির শেষের দিকে কীভাবে একটি নতুন লাইন থাকে না সে সম্পর্কে আমি যখন জিনিসগুলি করি তখন আমি বিভিন্ন বিষয়গুলি থেকে ভুতের প্রতিবেদনগুলি পেতে থাকি। আমি কীভাবে ভিএম দিয়ে কোনও ফাইল সম্পাদনা করব তা আমি সেখানে নতুন লাইন না রাখার জন্য এটি পেতে পারি না। সুতরাং এটি শুধু এটি করা vim।
স্টিভেন লু

1
@ এঞ্জোটিব: (setq require-final-newline 'ask)আমার.emacs
কিথ থম্পসন

3

কিছু পাইপলাইন প্রক্রিয়া করার সময় আপনি যদি কেবল নতুন লাইন যুক্ত করতে চান তবে এটি ব্যবহার করুন:

outputting_program | { cat ; echo ; }

এটি পসিক্স অনুগতও।

তারপরে অবশ্যই আপনি এটি কোনও ফাইলে পুনর্নির্দেশ করতে পারেন।


2
আমি পাইপলাইনে এটি ব্যবহার করতে পারি তা সহায়ক। এটি আমাকে শিরোনাম বাদ দিয়ে CSV ফাইলে সারি সংখ্যা গণনা করতে দেয় allows এবং এটি উইন্ডোজ ফাইলগুলিতে একটি সঠিক লাইন গণনা করতে সহায়তা করে যা কোনও নিউলাইন বা ক্যারেজ রিটার্নের সাথে শেষ হয় না। cat file.csv | tr "\r" "\n" | { cat; echo; } | sed "/^[[:space:]]*$/d" | tail -n +2 | wc -l
কাইল টোল

3

প্রদত্ত ইনপুটটিতে কোনও নাল নেই:

paste - <>infile >&0

... একটি পীড়নের লেজ প্রান্তে যদি ইতিমধ্যে এটি না থাকে তবে কেবল সর্বদা একটি নতুন লাইন যুক্ত করা যথেষ্ট। এবং এটি সঠিক হওয়ার জন্য কেবল একবার ইনপুট ফাইলটি পড়তে হবে।


এটি স্টিডিন এবং স্টডআউট একই ওপেন-ফাইলের বিবরণ ভাগ করে নেওয়ার মতো কাজ করবে না (সুতরাং ফাইলের মধ্যে কার্সার)। paste infile 1<> infileপরিবর্তে আপনার প্রয়োজন হবে।
স্টাফেন চেজেলাস

2

যদিও এটি সরাসরি প্রশ্নের উত্তর দেয় না, এখানে ফাইলগুলি সনাক্ত করতে আমি লিখিত একটি সম্পর্কিত স্ক্রিপ্ট যা নিউলাইনে শেষ হয় না। এটা খুব দ্রুত।

find . -type f | # sort |        # sort file names if you like
/usr/bin/perl -lne '
   open FH, "<", $_ or do { print " error: $_"; next };
   $pos = sysseek FH, 0, 2;                     # seek to EOF
   if (!defined $pos)     { print " error: $_"; next }
   if ($pos == 0)         { print " empty: $_"; next }
   $pos = sysseek FH, -1, 1;                    # seek to last char
   if (!defined $pos)     { print " error: $_"; next }
   $cnt = sysread FH, $c, 1;
   if (!$cnt)             { print " error: $_"; next }
   if ($c eq "\n")        { print "   EOL: $_"; next }
   else                   { print "no EOL: $_"; next }
'

পার্ল স্ক্রিপ্ট স্টিডিন থেকে ফাইলের নামের (allyচ্ছিকভাবে বাছাই করা) একটি তালিকা পড়ে এবং প্রতিটি ফাইলের জন্য এটি ফাইলটি একটি নতুন লাইনে শেষ হয় কিনা তা নির্ধারণ করার জন্য শেষ বাইটটি পড়ে। এটি খুব দ্রুত কারণ এটি প্রতিটি ফাইলের সম্পূর্ণ বিষয়বস্তু পড়া এড়ানো যায়। এটি প্রতিটি ফাইল এটি পড়ার জন্য একটি লাইন আউটপুট দেয়, "ত্রুটি:" দিয়ে উপসর্গ করা হয় যদি কোনও ধরণের ত্রুটি দেখা দেয় তবে "খালি:" ফাইলটি ফাঁকা থাকলে (নতুন লাইনের সাথে শেষ হয় না!), "EOL:" ("এর শেষে) লাইন ") ফাইলটি যদি নতুন লাইনের সাথে শেষ হয় এবং" নতুন কোনও EOL: "ফাইলটি যদি নতুন লাইনের সাথে শেষ না হয়।

দ্রষ্টব্য: স্ক্রিপ্টটি ফাইলের নামগুলি হ্যান্ডেল করে না যাতে নিউলাইন রয়েছে। আপনি যদি কোনও জিএনইউ বা বিএসডি সিস্টেমে থাকেন তবে আপনি সম্ভাব্য সমস্ত ফাইলের নামগুলি সন্ধানের জন্য--প্রিন্ট 0, -z সাজাতে, এবং -0 পার্লে যুক্ত করে এটি পরিচালনা করতে পারেন:

find . -type f -print0 | sort -z |
/usr/bin/perl -ln0e '
   open FH, "<", $_ or do { print " error: $_"; next };
   $pos = sysseek FH, 0, 2;                     # seek to EOF
   if (!defined $pos)     { print " error: $_"; next }
   if ($pos == 0)         { print " empty: $_"; next }
   $pos = sysseek FH, -1, 1;                    # seek to last char
   if (!defined $pos)     { print " error: $_"; next }
   $cnt = sysread FH, $c, 1;
   if (!$cnt)             { print " error: $_"; next }
   if ($c eq "\n")        { print "   EOL: $_"; next }
   else                   { print "no EOL: $_"; next }
'

অবশ্যই, আপনাকে এখনও আউটপুটটিতে নিউলাইনগুলি (পাঠকের অনুশীলন হিসাবে ছেড়ে দেওয়া) সহ ফাইলের নামগুলি এনকোড করার একটি উপায় নিয়ে আসতে হবে।

আউটপুট ফিল্টার করা যেতে পারে, যদি ইচ্ছা হয় তবে সেই ফাইলগুলিতে একটি নতুন লাইন যুক্ত করা যায়, যার মধ্যে খুব সহজেই থাকে

 echo >> "$filename"

চূড়ান্ত নিউলাইনটির অভাব স্ক্রিপ্টগুলিতে বাগের কারণ হতে পারে যেহেতু শেল এবং অন্যান্য ইউটিলিটিগুলির কিছু সংস্করণ সঠিকভাবে কোনও ফাইলটি পড়ার সময় অনুপস্থিত চূড়ান্ত নিউলাইন পরিচালনা করতে পারে না।

আমার অভিজ্ঞতায়, ফাইলগুলি সম্পাদনা করার জন্য বিভিন্ন উইন্ডোজ ইউটিলিটি ব্যবহার করে একটি চূড়ান্ত নতুন লাইনের অভাব দেখা দেয়। কোনও ফাইল সম্পাদনা করার সময় আমি কখনই ভিএমকে হারিয়ে যাওয়া চূড়ান্ত নিউলাইনটি দেখিনি, যদিও এটি এই জাতীয় ফাইলে রিপোর্ট করবে।

অবশেষে, অনেকগুলি ছোট (তবে ধীর) স্ক্রিপ্ট রয়েছে যা তাদের ফাইলের নাম ইনপুটগুলি লুপ করতে পারে সেই ফাইলগুলি মুদ্রণের জন্য যা নতুন লাইনে শেষ হয় না, যেমন:

/usr/bin/perl -ne 'print "$ARGV\n" if /.\z/' -- FILE1 FILE2 ...

1

vi/ vim/ exসম্পাদকদের স্বয়ংক্রিয়ভাবে যোগ <EOL>ফাইলের শেষে এ যদি না ফাইল আগে থেকেই এটা হয়েছে।

সুতরাং চেষ্টা করুন:

vi -ecwq foo.txt

যা এর সমান:

ex -cwq foo.txt

পরীক্ষামূলক:

$ printf foo > foo.txt && wc foo.txt
0 1 3 foo.txt
$ ex -scwq foo.txt && wc foo.txt
1 1 4 foo.txt

একাধিক ফাইল সংশোধন করতে, চেক করুন: প্রচুর ফাইলের জন্য 'ফাইলের শেষে কোনও নিউলাইন নেই' কিভাবে ঠিক করবেন? এসও তে

কেন এটি এত গুরুত্বপূর্ণ? আমাদের ফাইলগুলি পসিক্স সামঞ্জস্যপূর্ণ রাখতে ।


0

বর্তমান ডিরেক্টরিতে (প্লাস সাব-ডাইরেক্টরিগুলি) সমস্ত ফাইলে স্বীকৃত উত্তর প্রয়োগ করতে:

$ find . -type f -exec sed -i -e '$a\' {} \;

এটি লিনাক্স (উবুন্টু) এ কাজ করে। ওএস এক্স-এ আপনাকে সম্ভবত ব্যবহার করতে হবে -i ''(অরীক্ষিত)।


4
নোট করুন যে find .ফাইলগুলি সহ সমস্ত ফাইল তালিকাভুক্ত করে .git। বাদ দিতে:find . -type f -not -path './.git/*' -exec sed -i -e '$a\' {} \;
ফ্রাইডারব্লিউমলে

আশা করি আমি এটি চালানোর আগে এই মন্তব্যটি / এটি সম্পর্কে ভাবতাম। আচ্ছা ভালো.
kstev

0

কমপক্ষে জিএনইউ সংস্করণগুলিতে, ইতিমধ্যে উপস্থিত না থাকলে একটি চূড়ান্ত নিউলাইন যুক্ত করে , কেবলমাত্রgrep ''awk 1 তার ইনপুটটিকে সহজভাবে বা প্রমিত করে তোলে izes তারা এই প্রক্রিয়াতে ফাইলটি অনুলিপি করে থাকে, যা বড় হলে সময় নেয় (তবে উত্স যেভাবেই পড়তে হবে না খুব বড় হওয়া উচিত?) এবং আপনি যেমন কিছু না করে মোডটাইম আপডেট করেন

 mv file old; grep '' <old >file; touch -r old file

(যদিও এটি কোনও ফাইলের জন্য আপনি যাচাই-বাছাই করছেন তা ঠিক আছে কারণ আপনি এটি সংশোধন করেছেন) এবং আপনি আরও সতর্ক না হয়ে থাকলে এটি হার্ডলিঙ্কস, ননডাফল্ট অনুমতি এবং এসিএল ইত্যাদি হারাবে।


বা ঠিক grep '' file 1<> file, যদিও এটি এখনও পুরোপুরি ফাইলটি পড়তে এবং লিখতে পারে।
স্টাফেন চেজেলাস

-1

এটি এআইএক্স কেএস-তে কাজ করে:

lastchar=`tail -c 1 *filename*`
if [ `echo "$lastchar" | wc -c` -gt "1" ]
then
    echo "/n" >> *filename*
fi

আমার ক্ষেত্রে, ফাইলটি যদি নতুন লাইনটি অনুপস্থিত, wcকমান্ডটি একটি মান দেয় 2এবং আমরা একটি নতুন লাইন লিখি।


প্রতিক্রিয়াটি আপ বা ডাউনভোটগুলির আকারে আসবে, বা আপনাকে আপনার উত্তর / প্রশ্নগুলির আরও বেশি রূপরেখা দেওয়ার জন্য মন্তব্যে জিজ্ঞাসা করা হবে, উত্তরের শরীরে এটি জিজ্ঞাসা করার কোনও অর্থ নেই। এটি বিন্দুতে রাখুন, স্ট্যাকেক্সচেঞ্জে স্বাগতম!
k0pernikus

-1

যোগ করা হচ্ছে প্যাট্রিক Oscity এর উত্তর , যদি আপনি শুধু একটি নির্দিষ্ট ডিরেক্টরিতে এটা প্রয়োগ করতে চান, আপনি ব্যবহার করতে পারে:

find -type f | while read f; do tail -n1 $f | read -r _ || echo >> $f; done

যে ডিরেক্টরিতে আপনি নতুন লাইন যুক্ত করতে চান এটির ভিতরে এটি চালান।


-1

echo $'' >> <FILE_NAME> ফাইলের শেষে একটি ফাঁকা রেখা যুক্ত করবে।

echo $'\n\n' >> <FILE_NAME> ফাইলটির শেষে 3 টি ফাঁকা লাইন যুক্ত করবে।


স্ট্যাক এক্সচেঞ্জের একটি মজার বিন্যাস রয়েছে, আমি এটি আপনার জন্য স্থির করেছি :-)
পিটার

-1

যদি আপনার ফাইলটি উইন্ডোজ লাইনের শেষের সাথে সমাপ্ত হয় \r\nএবং আপনি লিনাক্সে থাকেন তবে আপনি এই sedআদেশটি ব্যবহার করতে পারেন । এটি \r\nইতিমধ্যে সেখানে না থাকলে কেবলমাত্র শেষ লাইনে যুক্ত হয়:

sed -i -e '$s/\([^\r]\)$/\1\r\n/'

ব্যাখ্যা:

-i    replace in place
-e    script to run
$     matches last line of a file
s     substitute
\([^\r]\)$    search the last character in the line which is not a \r
\1\r\n    replace it with itself and add \r\n

যদি শেষ লাইনে ইতিমধ্যে একটি থাকে \r\nতবে অনুসন্ধানের regexp মিলবে না, তাই কিছুই হবে না।


-1

আপনি এর fix-non-delimited-lineমতো স্ক্রিপ্ট লিখতে পারেন:

#! /bin/zsh -
zmodload zsh/system || exit
ret=0
for file do
  if sysopen -rwu0 -- "$file"; then
    if sysseek -w end -1; then
      read -r x || print -u0
    else
      syserror -p "Can't seek in $file before the last byte: "
      ret=1
    fi
  else
    ret=1
  fi
done
exit $ret

এখানে প্রদত্ত কয়েকটি সমাধানের বিপরীতে, এটি

  • এটি দক্ষ হতে হবে যাতে এটি কোনও প্রক্রিয়া কাঁটাচামচ করে না, প্রতিটি ফাইলের জন্য কেবল একটি বাইট পড়ে এবং ফাইলটি পুনরায় লেখায় না (কেবল একটি নতুন লাইন সংযোজন করে)
  • সিমলিঙ্ক / হার্ডলিঙ্কগুলি ভেঙে ফেলবে না বা মেটাডেটা প্রভাব ফেলবে না (সিলেট / এমটাইম কেবল তখনই আপডেট হয় যখন একটি নতুন লাইন যুক্ত হয়)
  • শেষ বাইটটি NUL বা মাল্টি-বাইট চরিত্রের অংশ হলেও এমনকি ঠিক আছে work
  • ফাইলের নামগুলিতে কী অক্ষর বা অ-অক্ষর থাকতে পারে তা নির্ধারণ না করেই ঠিক আছে
  • সঠিকভাবে অপঠনযোগ্য বা অলিখিত লিখনযোগ্য বা অদেখাযোগ্য ফাইলগুলি হ্যান্ডেল করা উচিত (এবং তদনুযায়ী ত্রুটিগুলি রিপোর্ট করুন)
  • খালি ফাইলগুলিতে একটি নতুন লাইন যুক্ত করা উচিত নয় (তবে সেই ক্ষেত্রে একটি অবৈধ সন্ধান সম্পর্কে ত্রুটির খবর দেয়)

আপনি উদাহরণস্বরূপ এটি ব্যবহার করতে পারেন:

that-script *.txt

বা:

git ls-files -z | xargs -0 that-script

POSIXly, আপনি এর সাথে সমতুল্য কিছু করতে পারেন

export LC_ALL=C
ret=0
for file do
  [ -s "$file" ] || continue
  {
    c=$(tail -c 1 | od -An -vtc)
    case $c in
      (*'\n'*) ;;
      (*[![:space:]]*) printf '\n' >&0 || ret=$?;;
      (*) ret=1;; # tail likely failed
    esac
  } 0<> "$file" || ret=$? # record failure to open
done
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.