পাইথন পাঠ্য ফাইল কনটেনেট করে


168

আমার মতো 20 টি ফাইলের নামের একটি তালিকা রয়েছে ['file1.txt', 'file2.txt', ...]। এই ফাইলগুলিকে নতুন ফাইলে যুক্ত করতে আমি পাইথন স্ক্রিপ্ট লিখতে চাই। আমি প্রতিটি ফাইল খুলতে পারি f = open(...), কল করে লাইন লাইন পড়তে পারি f.readline()এবং প্রতিটি লাইন সেই নতুন ফাইলে লিখতে পারি। এটি আমার কাছে খুব "মার্জিত" বলে মনে হচ্ছে না, বিশেষ করে যে অংশটি আমাকে পড়তে হবে // লাইন দিয়ে লাইনে লিখতে হবে।

পাইথনে এটি করার আরও কি আরও "মার্জিত" উপায় আছে?


7
এটি অজগর নয়, শেল স্ক্রিপ্টিং এ আপনি এমন কিছু করতে পারেন cat file1.txt file2.txt file3.txt ... > output.txt। অজগরটিতে, আপনি যদি পছন্দ না readline()করেন তবে সর্বদা readlines()বা সরলভাবে থাকে read()
jedwards

1
@ জেডওয়ার্ডস কেবল মডিউলটি cat file1.txt file2.txt file3.txtব্যবহার করে কমান্ডটি চালান subprocessএবং আপনার কাজ শেষ। তবে আমি জানিনা catউইন্ডোজে কাজ করে কিনা ।
অশ্বিনী চৌধুরী চৌধুরী

5
একটি দ্রষ্টব্য হিসাবে, আপনি যেভাবে বর্ণনা করেছেন সেটি হ'ল একটি ফাইল পড়ার এক ভয়ঙ্কর উপায়। withআপনার ফাইলগুলি সঠিকভাবে বন্ধ হয়েছে কিনা তা নিশ্চিত করতে স্টেটমেন্টটি ব্যবহার করুন এবং ব্যবহার না করে লাইন পেতে ফাইলটির উপরে পুনরাবৃত্তি করুন f.readline()
গ্যারেথ ল্যাটি

পাঠ্য ফাইলটি ইউনিকোড করার সময় @ জেওয়ার্ডস বিড়াল কাজ করে না।
অভি কোহেন

প্রকৃত বিশ্লেষণ waymoot.org/home/python_string
নিউ এভারেস্ট

উত্তর:


258

এটি করা উচিত

বড় ফাইলগুলির জন্য:

filenames = ['file1.txt', 'file2.txt', ...]
with open('path/to/output/file', 'w') as outfile:
    for fname in filenames:
        with open(fname) as infile:
            for line in infile:
                outfile.write(line)

ছোট ফাইলগুলির জন্য:

filenames = ['file1.txt', 'file2.txt', ...]
with open('path/to/output/file', 'w') as outfile:
    for fname in filenames:
        with open(fname) as infile:
            outfile.write(infile.read())

… এবং আর একটি আকর্ষণীয় যা আমি ভেবেছিলাম :

filenames = ['file1.txt', 'file2.txt', ...]
with open('path/to/output/file', 'w') as outfile:
    for line in itertools.chain.from_iterable(itertools.imap(open, filnames)):
        outfile.write(line)

দুঃখের বিষয়, এই শেষ পদ্ধতিটি কয়েকটি উন্মুক্ত ফাইল বর্ণনাকারী ফেলেছে, যা জিসি যেভাবেই করা উচিত। আমি কেবল এটি আকর্ষণীয় মনে হয়েছিল


9
এটি, বড় ফাইলগুলির জন্য, খুব স্মৃতিশক্তি অযোগ্য হবে।
গ্যারেথ ল্যাটি

1
@ ইন্সপেক্টর জি 4ডেজ: আমি আপনাকে জিজ্ঞাসা করছিলাম না, আমি আইকামকে জিজ্ঞাসা করছিলাম, যিনি অভিযোগ করেছিলেন যে আপনার সমাধানটি কার্যকর হবে না। আমি বাজি রাখতে ইচ্ছুক যে এটি অপের ব্যবহারের ক্ষেত্রে যথেষ্ট দক্ষতার চেয়ে বেশি এবং আইকামের যে কোনও ব্যবহারের ক্ষেত্রে বিবেচনা করা উচিত। যদি তিনি মনে করেন যে এটি তা নয় তবে আপনি এটি অনুকূলিত করার দাবি করার আগে এটি প্রমাণ করা তার দায়িত্ব।
নভেম্বর'১২ এ 21

2
আমরা একটি বড় ফাইল হতে বিবেচনা করা হয়?
দি

4
@ ডি: একটি ফাইল এত বড় যে এটির মূল বিষয়গুলি মেমরির সাথে খাপ খায় না
ইন্সপেক্টর

7
কেবল পুনরাবৃত্তি করা: এটি ভুল উত্তর, shutil.copyfileobj সঠিক উত্তর।
পল ক্রোলি

193

ব্যবহার shutil.copyfileobj

এটি স্বয়ংক্রিয়ভাবে আপনার জন্য খণ্ড দ্বারা ইনপুট ফাইলগুলি পড়ে, যা আরও বেশি দক্ষ এবং ইনপুট ফাইলগুলি পড়া এবং এতে কিছু ইনপুট ফাইল মেমরির সাথে ফিট করার জন্য খুব বড় হলেও কার্যকর হবে:

import shutil

with open('output_file.txt','wb') as wfd:
    for f in ['seg1.txt','seg2.txt','seg3.txt']:
        with open(f,'rb') as fd:
            shutil.copyfileobj(fd, wfd)

2
for i in glob.glob(r'c:/Users/Desktop/folder/putty/*.txt'):আমি সমস্ত ফাইল ডিরেক্টরিতে অন্তর্ভুক্ত করার জন্য বিবৃতিটির জন্য প্রতিস্থাপন করেছি তবে আমার output_fileখুব দ্রুত সময়ের মধ্যে 100 গিগাবাইটের মতো সত্যিই বিশাল বৃদ্ধি শুরু হয়েছিল।
আর__রাকি__

10
দ্রষ্টব্য, এটি EOL অক্ষর না থাকলে পরবর্তী ফাইলের প্রথম স্ট্রিংগুলির সাথে প্রতিটি ফাইলের শেষ স্ট্রিংগুলি একত্রিত করবে। আমার ক্ষেত্রে এই কোডটি ব্যবহারের পরে আমি সম্পূর্ণরূপে দূষিত ফলাফল পেয়েছি। আমি স্বাভাবিক ফলাফল পেতে কপিফিলোবজ-এর পরে wfd.write (b "\ n") যুক্ত করেছি
থেলামোফোফোট

1
@ থ্যালাম্বোবোট আমি বলব যে এই ক্ষেত্রে নিখুঁত বক্তব্য নয়, আরে, আপনার প্রয়োজন অনুসারে যাই হোক না কেন।
হ্যালো গুডবাই

59

ঠিক কি fileinput জন্য:

import fileinput
with open(outfilename, 'w') as fout, fileinput.input(filenames) as fin:
    for line in fin:
        fout.write(line)

এই ব্যবহারের ক্ষেত্রে, ফাইলগুলিতে ম্যানুয়ালি পুনরাবৃত্তি করার চেয়ে এটি খুব সহজ নয়, তবে অন্যান্য ক্ষেত্রে, একক পুনরাবৃত্তকারী থাকা যা সমস্ত ফাইলগুলিতে পুনরাবৃত্তি করে যেমন এটি একটি একক ফাইল খুব সহজ y (এছাড়াও, fileinputপ্রতিটি ফাইল শেষ হওয়ার সাথে সাথেই এটি বন্ধ হয়ে যায় এর অর্থ হ'ল প্রত্যেকটির কোনও প্রয়োজন নেই withবা তা closeনয়, তবে এটি কেবল একটি লাইন সঞ্চয়, কোনও চুক্তির এত বড় নয়))

এগুলিতে আরও কিছু নিফটি বৈশিষ্ট্য রয়েছে fileinputযেমন প্রতিটি লাইন ফিল্টার করে ফাইলের স্থান পরিবর্তন করার ক্ষমতা like


যেমন মন্তব্যগুলিতে উল্লিখিত হয়েছে, এবং অন্য পোস্টে আলোচনা হয়েছে , fileinputপাইথন ২. 2. নির্দেশিত হিসাবে কাজ করবে না। কোডটি পাইথন ২.7 এর সাথে সামঞ্জস্য করার জন্য এখানে সামান্য পরিবর্তন

with open('outfilename', 'w') as fout:
    fin = fileinput.input(filenames)
    for line in fin:
        fout.write(line)
    fin.close()

@ ল্যাটিওয়্যার: আমার মনে হয় যে বেশিরভাগ লোকেরা যারা শিখেন fileinputতাদের বলা হয় যে এটি একটি সরল sys.argv(বা পরে optparse/ ইত্যাদি পরে আরগস হিসাবে কী বাকী আছে ) তুচ্ছ স্ক্রিপ্টগুলির জন্য একটি বড় ভার্চুয়াল ফাইলে পরিণত করার উপায় , এবং এটি কোনও কিছুর জন্য ব্যবহার করার কথা ভাবেন না অন্যথায় (উদাহরণস্বরূপ, যখন তালিকাটি কমান্ড-লাইন আর্টস নয়) বা তারা শিখতে পারে তবে তারপরে ভুলে যায় — আমি প্রতি বছর বা দু'বার এটিকে পুনরায় আবিষ্কার করতে
থাকি

1
@ বেসামেন্ট আমার কাছে মনে for line in fileinput.input()হয় এই বিশেষ ক্ষেত্রে চয়ন করার সর্বোত্তম উপায় নয়: ওপি ফাইলগুলি একত্রীকরণ করতে চায়, লাইন দিয়ে সেগুলি পড়তে চায় না যা বাস্তবায়নের জন্য তাত্ত্বিকভাবে দীর্ঘতর প্রক্রিয়া
Eyequem

1
@ এেকেম: এটি কার্যকর করার দীর্ঘ প্রক্রিয়া নয়। আপনি যেমন উল্লেখ করেছেন, লাইন-ভিত্তিক সমাধানগুলি একবারে একটি চরিত্র পড়বে না; তারা খণ্ডে পড়ে এবং একটি বাফার থেকে লাইনগুলি টেনে নেয়। আই / ও সময় লাইন পার্সিংয়ের সময়টিকে পুরোপুরি সোয়াম করে দেবে, সুতরাং যতক্ষণ না বাস্তবায়নকারী বাফারিংয়ে মারাত্মক বোকা কিছু না করে, তত দ্রুত হবে (এবং সম্ভবত একটি ভাল বাফার ধরে অনুমান করার চেষ্টা করার চেয়েও দ্রুত নিজেকে আকার দিন, যদি আপনি ভাবেন 10000 একটি ভাল পছন্দ)।
28-30

1
@ বার্নার্ট কোন, 10000 একটি ভাল পছন্দ নয়। এটি আসলে খুব খারাপ পছন্দ কারণ এটি 2 এর শক্তি নয় এবং এটি হাস্যকরভাবে কিছুটা আকারের। আরও ভাল আকার 2097152 (2 21), 16777216 (2 24) বা এমনকি 134217728 (2 ** 27) হবে, কেন ?, 128 এমবি 4 জিবি র‌্যামে কিছুই নয়।
eyquem

2
উদাহরণ কোড পাইথন 2.7.10 জন্য বেশ বৈধ এবং পরে না: stackoverflow.com/questions/30835090/...
CnrL

8

আমি কমনীয়তা সম্পর্কে জানি না, তবে এটি কাজ করে:

    import glob
    import os
    for f in glob.glob("file*.txt"):
         os.system("cat "+f+" >> OutFile.txt")

8
আপনি এমনকি লুপ এড়াতে পারেন: ওএস আমদানি; os.system ("বিড়াল ফাইল * .txt >> আউটফিল.টেক্সট")
lib

6
ক্রস প্ল্যাটফর্ম নয় এবং এগুলিতে ফাঁকা জায়গাগুলির সাথে ফাইলের নাম ভাঙবে
উড়ন্ত ভেড়া

3
এটি অনিরাপদ; এছাড়াও, catফাইলগুলির একটি তালিকা নিতে পারে, তাই বারবার এটি কল করার প্রয়োজন নেই। আপনি সহজেই কল করে এটি নিরাপদ করতে পারেন subprocess.check_callপরিবর্তেos.system
Clément

5

ইউনিক্স কমান্ডে কী সমস্যা? (প্রদত্ত যে আপনি উইন্ডোজে কাজ করছেন না):

ls | xargs cat | tee output.txt কাজ করে (আপনি চাইলে উপকেন্দ্র দিয়ে অজগর থেকে কল করতে পারেন)


21
কারণ এটি অজগর সম্পর্কে একটি প্রশ্ন।
অস্পষ্টরবোট

2
সাধারণভাবে কোনও ভুল নয়, তবে এই উত্তরটি নষ্ট হয়ে গেছে (ls এর আউটপুটটি xargs এ পাস করবেন না, কেবল ফাইলের তালিকাটি সরাসরি বিড়ালের কাছে পাস করুন cat * | tee output.txt:)।
ক্লাইমেন্ট

যদি এটি ফাইলের নামও sertোকাতে পারে তবে তা দুর্দান্ত।
ডেকিং করা হচ্ছে

@ ডিকিং ইনপুট ফাইলের নাম নির্দিষ্ট করতে, আপনি ব্যবহার করতে পারেনcat file1.txt file2.txt | tee output.txt
GoTrained

1
... এবং আপনি 1> /dev/nullকমান্ডের শেষে যোগ করে
স্টার্টআউট

4
outfile.write(infile.read()) # time: 2.1085190773010254s
shutil.copyfileobj(fd, wfd, 1024*1024*10) # time: 0.60599684715271s

একটি সাধারণ বেঞ্চমার্ক দেখায় যে শুটিল আরও ভাল সম্পাদন করে।


3

@ ইন্সপেক্টর জি 4ডেট উত্তরের বিকল্প (তারিখের সেরা উত্তর 29-03-2016)। আমি 436MB এর 3 টি ফাইল দিয়ে পরীক্ষা করেছি।

@ ইন্সপেক্টর জি 4 ডেট সমাধান: 162 সেকেন্ড

নিম্নলিখিত সমাধান: 125 সেকেন্ড

from subprocess import Popen
filenames = ['file1.txt', 'file2.txt', 'file3.txt']
fbatch = open('batch.bat','w')
str ="type "
for f in filenames:
    str+= f + " "
fbatch.write(str + " > file4results.txt")
fbatch.close()
p = Popen("batch.bat", cwd=r"Drive:\Path\to\folder")
stdout, stderr = p.communicate()

"পুরানো ভাল প্রযুক্তির" সুবিধা গ্রহণ করে একটি ব্যাচ ফাইল তৈরি এবং এটি সম্পাদন করার ধারণা। এটি আধা পাইথন তবে দ্রুত কাজ করে। উইন্ডোজ জন্য কাজ করে।


3

ডিরেক্টরিতে যদি আপনার কাছে প্রচুর ফাইল থাকে তবে glob2হাতে হাতের লেখার পরিবর্তে ফাইলের একটি তালিকা উত্পন্ন করার জন্য এটি আরও ভাল বিকল্প হতে পারে।

import glob2

filenames = glob2.glob('*.txt')  # list of all .txt files in the directory

with open('outfile.txt', 'w') as f:
    for file in filenames:
        with open(file) as infile:
            f.write(infile.read()+'\n')

2

ফাইল অবজেক্টের .read () পদ্ধতিটি দেখুন:

http://docs.python.org/2/tutorial/inputoutput.html#methods-of-file-objects

আপনি যেমন কিছু করতে পারেন:

concat = ""
for file in files:
    concat += open(file).read()

বা আরও 'মার্জিত' পাইথন-ওয়ে:

concat = ''.join([open(f).read() for f in files])

যা এই নিবন্ধ অনুসারে: http://www.skymind.com/~ocrow/python_string/ এছাড়াও দ্রুত হবে।


10
এটি একটি বিশাল স্ট্রিং তৈরি করবে, যা ফাইলের আকারের উপর নির্ভর করে উপলভ্য মেমরির চেয়ে বড় হতে পারে। পাইথন ফাইলগুলিতে সহজে অলস অ্যাক্সেস সরবরাহ করে, এটি একটি খারাপ ধারণা।
গ্যারেথ ল্যাটি

2

ফাইলগুলি বিশাল না হলে:

with open('newfile.txt','wb') as newf:
    for filename in list_of_files:
        with open(filename,'rb') as hf:
            newf.write(hf.read())
            # newf.write('\n\n\n')   if you want to introduce
            # some blank lines between the contents of the copied files

ফাইলগুলি পুরোপুরি র‌্যামে পড়তে ও ধরে রাখতে যদি বড় হয় তবে read(10000)উদাহরণস্বরূপ , নির্দিষ্ট দৈর্ঘ্যের অংশগুলি লুপে অনুলিপি করতে প্রতিটি ফাইলটি পড়ার জন্য অ্যালগরিদমটি কিছুটা আলাদা হতে হবে ।


@ ল্যাটিওয়্যার, কারণ আমি নিশ্চিত যে মৃত্যুদন্ড কার্যকর করা দ্রুত হয়। উপায় দ্বারা, আসলে, কোডটি যখন লাইন দ্বারা একটি ফাইল লাইন পড়ার আদেশ দেয়, তখন ফাইলটি খণ্ডগুলি পড়ে থাকে, যা ক্যাশে রাখা হয় যার মধ্যে প্রতিটি লাইন একের পর এক পড়তে হয়। আরও ভাল পদ্ধতিটি হ'ল পাঠের অংশের দৈর্ঘ্যকে ক্যাশের আকারের সমান করে দেওয়া। তবে আমি জানি না কীভাবে এই ক্যাশের আকার নির্ধারণ করা যায়।
আইকেম

সিপিথনে এটি বাস্তবায়ন, তবে এর কোনওটিরই নিশ্চয়তা নেই। এটির মতো অনুকূলকরণ করা একটি খারাপ ধারণা হিসাবে এটি কিছু সিস্টেমে কার্যকর হতে পারে তবে এটি অন্যের জন্যও নাও হতে পারে।
গ্যারেথ লেটি

1
হ্যাঁ, অবশ্যই লাইন বাই লাইন পড়ার বিষয়টি বাফার করেছে। ঠিক এ কারণেই এটি এত ধীর নয়। (প্রকৃতপক্ষে, কিছু ক্ষেত্রে এটি কিছুটা দ্রুতও হতে পারে, কারণ যে কেউ আপনার প্ল্যাটফর্মে পাইথনকে পোর্ট করেছেন তিনি 10000 এর চেয়ে অনেক বেশি ভাল আকার বেছে নিয়েছেন)) যদি এর কার্য সম্পাদন সত্যিই গুরুত্বপূর্ণ হয় তবে আপনাকে বিভিন্ন বাস্তবায়নের প্রোফাইল দিতে হবে। তবে 99.99 ...% সময়, উভয় দিকই যথেষ্ট দ্রুতগতির চেয়ে বেশি, বা আসল ডিস্ক I / O হ'ল ধীর অংশ এবং এটি আপনার কোড কী করে তা বিবেচ্য নয়।
নভেম্বর'২২ এ 20 এয়ার্নার্ট

এছাড়াও, যদি আপনাকে সত্যিই বাফারিংটিকে ম্যানুয়ালি অপ্টিমাইজ করার প্রয়োজন হয় তবে আপনি ব্যবহার করতে চাইবেন os.openএবং os.readকারণ প্লেইন openসিটির স্টেডিওর চারপাশে পাইথনের মোড়ক ব্যবহার করে যার অর্থ 1 বা 2 অতিরিক্ত বাফার আপনার পথে চলেছে।
28:25

পিএস, কেন 10000 খারাপ: আপনার ফাইলগুলি সম্ভবত একটি ডিস্কে রয়েছে, ব্লকগুলি রয়েছে যা বাইটগুলির কিছুটা দীর্ঘ শক্তি। ধরা যাক তারা 4096 বাইট। সুতরাং, 10000 বাইট পড়ার অর্থ দুটি ব্লক পড়া, তারপরের পরবর্তী অংশ। আরও ১০০০০০ পড়ার অর্থ হ'ল পরের বাকী অংশগুলি, তারপরে দুটি ব্লক, তারপরের পরবর্তী অংশটি পড়া। আপনার কত আংশিক বা সম্পূর্ণ ব্লক পড়েছেন তা গণনা করুন এবং আপনি প্রচুর সময় নষ্ট করছেন। ভাগ্যক্রমে, পাইথন, স্টডিও, ফাইল সিস্টেম এবং কার্নেল বাফারিং এবং ক্যাচিং এই সমস্যাগুলির বেশিরভাগটি আপনার কাছ থেকে আড়াল করবে, তবে কেন এগুলি প্রথম স্থানে তৈরি করার চেষ্টা করবে?
অবতারিত

0
def concatFiles():
    path = 'input/'
    files = os.listdir(path)
    for idx, infile in enumerate(files):
        print ("File #" + str(idx) + "  " + infile)
    concat = ''.join([open(path + f).read() for f in files])
    with open("output_concatFile.txt", "w") as fo:
        fo.write(path + concat)

if __name__ == "__main__":
    concatFiles()

-2
  import os
  files=os.listdir()
  print(files)
  print('#',tuple(files))
  name=input('Enter the inclusive file name: ')
  exten=input('Enter the type(extension): ')
  filename=name+'.'+exten
  output_file=open(filename,'w+')
  for i in files:
    print(i)
    j=files.index(i)
    f_j=open(i,'r')
    print(f_j.read())
    for x in f_j:
      outfile.write(x)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.