tags:

views:

201

answers:

2

Has anyone written the GNU cat command in python and would be willing to share? GNU cat actually does quite a bit & I don't really feel like re-inventing the wheel today. Yes, I did do a google search & and after reading too many sad stories of kittens vs snakes I decided to try SO.

Edit: I'd like to modify it so that it only shows unique lines.

+2  A: 

That depends which functionalities you want. If you just want to print out a file, you can do

with open('myfile') as f:
    for line in f:
        print line,

or to concatenate some files, you could do

filenames = ['file1', 'file2', 'file3']
for filename in filenames:
    with open(filename) as f:
        for line in f:
            print line,

There is no general answer. Depending on the functionality you want to replicate, your code will be different. To exactly replicate something odd and special, use the subprocess module and call cat.

If you want to implement the same interface as cat, that seems an odd requirement. You can call cat and you can write the code more naturally. The only reason I can think to completely reimplement cat is for homework, and I would hope you wouldn't ask for the finished product if that is your reason.

Mike Graham
Sorry, didn't make it clear. I'm wondering if someone has written something to exactly replicate GNU cat.
JohnnyLambada
No, not for homework -- I want to use it as a basis for other commands. Thanks for your answer, I used it as a basis for catuniq. See my answer for the source.
JohnnyLambada
+3  A: 

Latest: Thank's Ned for the fileinput tip! Here's the latest:

#!/usr/bin/python

"""cat the file, but only the unique lines
"""
import fileinput

if __name__ == "__main__":
    lines=set()
    for line in fileinput.input():
        if not line in lines:
            print line,
            lines.add(line)

Previously (2010-02-09):

Here's what I ended up with. It works for my immediate need. Thanks Mike Graham for your help.

#!/usr/bin/python
"""cat the file, but only the unique lines
"""
import optparse
import sys

if __name__ == "__main__":
    parser = optparse.OptionParser()
    parser.set_usage('%prog [OPTIONS]')
    parser.set_description('cat a file, only unique lines')

    (options,args) = parser.parse_args()

    lines = set()
    for file in args:
        if file == "-":
            f = sys.stdin
        else:
            f = open(file)
        for line in f:
            if not line in lines:
                print line,
                lines.add(line)
JohnnyLambada
Since `line in lines` is O(n) for lists you have O(N^2) runtime here. You can fix that by making lines a set, which has O(1) membership test: `lines = set()`.
bayer
fixed, thanks bayer! I tried this on a 30k line file, and the runtime went from 15secs to <1sec
JohnnyLambada
Look at the fileinput module in the standard library. You could replace most of your code with one line. http://docs.python.org/library/fileinput.html
Ned Deily
Thanks, Ned -- fileinput chopped the line count from 17 to 7 lines!
JohnnyLambada