42

I have been searching online, but have not found any good solution.

Here is my text file:

[54, 95, 45, -97, -51, 84, 0, 32, -55, 14, 50, 54, 68, -3, 57, 88, -1]
[24, 28, 38, 37, 9, 44, -14, 84, -40, -92, 86, 94, 95, -62, 12, -36, -12]
[-26, -67, -89, -7, 12, -20, 76, 88, -15, 38, -89, -65, -53, -84, 31, -81, -91]
[-19, -50, 16, 47, -42, -31, 75, 0, 25, -95, 75, 97, 19, 77, -2, -31, -59]
[-66, -10, 35, -39, 24, 70, 74, -45, -27, 77, -44, 86, 57, 14, -91, -26, -20]
[-63, 80, -31, 70, 100, 22, -30, 74, 44, -35, -25, -75, -39, -13, -93, 0, 1]
[63, 13, 67, 55, -56, 45, 10, 61, -14, -55, 40, 84, -59, 7, 75, -64, -25]
[7, -50, -17, -86, -43, 34, 82, 84, 49, 18, 56, -31, -19, 59, -96, 72, -40]
[-73, 34, -68, 20, 30, 1, 49, 77, -94, 2, -83, 40, 2, 20, 66, 60, -36]
[-80, -12, 93, 77, 73, -55, 24, 3, -60, 12, -41, -43, -49, 36, 6, -93, -24]
[-41, 12, -43, 42, -70, 75, -84, -83, 30, 78, -3, 51, 69, 0, 65, 60, -15]
[82, 97, -57, -96, 25, -100, 61, 13, -80, -32, 99, 60, 58, -58, -45, -58, -53]
[-90, -34, 80, 95, -12, -34, 71, -83, 46, 10, -78, -40, 65, 53, -81, 40, -59]
[-80, -20, -87, -2, -54, 74, -79, 22, -20, 60, -84, -12, -40, -98, -81, -5, -35]
[33, 36, -46, 10, -77, 88, -99, -5, 19, -20, 89, 87, -47, 46, 10, 17, -67]
[-77, 73, 20, 44, 79, -14, -8, -49, 45, -49, -91, -21, 41, -13, 74, -71, -15]
[98, -99, 51, 53, 56, -78, 31, 45, 35, -36, -10, -86, 9, 94, 24, -2, -20]
[-37, 46, -77, -92, 48, -34, 75, 19, -74, -13, -100, 33, -46, 19, -60, 5, 5]
[-13, -30, -82, -70, 64, 87, 16, 67, -36, 22, -99, -92, 36, 8, 90, 48, -5]
[46, 75, -15, 24, 24, -37, -3, -45, 32, -84, -2, -16, 43, -88, 92, 27, -10]

All I want is to delete the first line (which means using the second line as the first line, not filling first line with whitespace).

Could anyone please help me with that?

martineau
  • 119,623
  • 25
  • 170
  • 301
zaolian
  • 1,187
  • 3
  • 11
  • 21
  • 3
    you should not use python for this, rather just use a bash command sed -i -e "1d" $FILE – WindowsMaker Dec 04 '13 at 00:20
  • 5
    Maybe python isn't the weapon of choice for this. A simple `tail -n +2 "$FILE"` should do the trick? – Hyperboreus Dec 04 '13 at 00:21
  • 19
    @Hyperboreus If the user wants to use Python, then so be it. There are quick ways to do this in Python as well as any other language. – Rushy Panchal Dec 04 '13 at 00:43
  • 3
    @F3AR3DLEGEND Sure thing. I just wanted to point out another way, in case OP was too fixed on python (which I do not know). You know: "If the only tool you know is a hammer, all problems look like nails". – Hyperboreus Dec 04 '13 at 01:03
  • 1
    @zaftcoAgeiha : It might needed to be done from within a python application itself, like in my case and the reason I came here for : ) . I did the same using "sed command" invoked on the shell from python script but my code reviewer didn't want to spawn a new process for such a simple thing..... Both have pros and cons, like in file.read() file needs to be read in memory and can be an issue for large files but I need to get my code checked in first : ) – ViFI Jul 09 '16 at 00:55
  • 1
    For strings instead of file: https://stackoverflow.com/questions/30833409/python-deleting-the-first-2-lines-of-a-string – Ciro Santilli OurBigBook.com Nov 10 '18 at 13:46
  • 1
    @CiroSantilli冠状病毒审查六四事件法轮功 Just what I was looking for – user324747 May 31 '20 at 23:15

9 Answers9

63

Assuming you have enough memory to hold everything in memory:

with open('file.txt', 'r') as fin:
    data = fin.read().splitlines(True)
with open('file.txt', 'w') as fout:
    fout.writelines(data[1:])

We could get fancier, opening the file, reading and then seeking back to the beginning eliminating the second open, but really, this is probably good enough.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • 3
    `head, tail = fin.read().split('\n', 1); ...; fout.write(tail)` is probably more efficient. – coldfix Aug 10 '17 at 12:40
  • @coldfix -- Yeah, you might be right. Though you'll likely spend _most_ of your time sitting in IO so it probably doesn't make _too_ much difference. – mgilson Aug 10 '17 at 17:02
  • This is not safe when you're using the file from more threads, or something else also uses the file. In theory, it is possible to read without removing the first line. After you run again, you will get the same line - it's not safe when working with money, or something important data. – DaWe Mar 06 '20 at 14:06
  • Sure -- if you expect to be mutating state like this with threads it's never going to be threadsafe -- It's up to you to acquire an appropriate lock to prevent nasty race conditions or whatever. – mgilson Mar 09 '20 at 20:26
  • No need to open() the file twice - it is insecure when you run it asyncronously. You can lose data because you're reading something outdated while the updated string is not written into the file. [Better solution](https://stackoverflow.com/a/60565865/8474284) – DaWe Apr 01 '22 at 14:25
15

Here is a memory-efficient (?) solution which makes use of shutil:

import shutil

source_file = open('file.txt', 'r')
source_file.readline()
# this will truncate the file, so need to use a different file name:
target_file = open('file.txt.new', 'w')

shutil.copyfileobj(source_file, target_file)
coldfix
  • 6,604
  • 3
  • 40
  • 50
rbtsbg
  • 163
  • 1
  • 4
  • No need to open() the file twice - it is insecure when you run it asyncronously. You can lose data because you're reading something outdated while the updated string is not written into the file. [Better solution](https://stackoverflow.com/a/60565865/8474284) – DaWe Apr 01 '22 at 14:26
8

You can do it much easier by simply stating what is the first line to be read:

    with open(filename, "r") as f:
        rows = f.readlines()[1:]
7

Safer to use one open() for read & write, so you won't lose data if you want to use the file from another thread/process:

def pop(self, file):
    with open(file, 'r+') as f: # open file in read / write mode
        firstLine = f.readline() # read the first line and throw it out
        data = f.read() # read the rest
        f.seek(0) # set the cursor to the top of the file
        f.write(data) # write the data back
        f.truncate() # set the file size to the current size
        return firstLine

fifo = pop('filename.txt')
phoenix
  • 7,988
  • 6
  • 39
  • 45
DaWe
  • 1,422
  • 16
  • 26
4

This solution will work for big files that don't fit into memory by reading and writing one line at a time:

import os
from shutil import move
from tempfile import NamedTemporaryFile

# Take off the first line which has the system call and params
file_path = 'xxxx'
temp_path = None
with open(file_path, 'r') as f_in:
    with NamedTemporaryFile(mode='w', delete=False) as f_out:
        temp_path = f_out.name
        next(f_in)  # skip first line
        for line in f_in:
            f_out.write(line)

os.remove(file_path)
move(temp_path, file_path)
Dewald Abrie
  • 1,392
  • 9
  • 21
0

Bash will be faster for that purpose. You can use these in you python script:

subprocess.Popen.communicate()

I wrote a function for running a subprocess cmd for shell:

def popen_method(call):
    subprocess_call = Popen([call], shell=True, stdout=PIPE, stderr=PIPE)
    out, err = subprocess_call.communicate()
    if err:
        raise yourError(
            '\n============= WARNING/ERROR ===============\n{}\n===========================================\n'.format(
                err.rstrip()))
    return out

You call it like this:

testing = "sed -i /var/output/ip_list.csv -e '1 s/^.*$/host_id,ip,last_updated/g'"
popen_method(testing)

or use:

from sh import sed

then run the sed command:

sed -i /var/output/ip_list.csv -e '1 s/^.*$/host_id,ip,last_updated/g'

This will replace whatever you had on the first line with host_id,ip,last_updated.

miken32
  • 42,008
  • 16
  • 111
  • 154
sweluhu
  • 11
  • 1
  • Crucial part of sed is: '1 s/^.*$/host_id,ip,last_updated/g' where 1 remove the first line( you can also do sed "1d") and s/^.$/wtv here that will replace/g this will substitute from ^ beginning line to end line $ with "wtv here..." g=globally – sweluhu Sep 06 '16 at 22:06
0

Just a suggestion, cause I faced the same problem with the difference that I didn't want to delete the first raw from the original .txt file just to use the content from the 2nd raw and on.

I use the simple solution of

with open(file) as f:
    content = f.readlines()
    content = content[1:]

This is always the case if you don't want to permanently delete the content of the file.

0

I too wanted to read the first line of a file:

# open the file and read the contents
fp = open(file_path_name)
content = fp.readline()                 # read just the first line
print(content)

Worked well for me.

EdB
  • 9
  • 2
0

This is my code for removing the first line from a file I hope it helps you

  with open(r"dark.json", 'r+') as fp:
  # read an store all lines into list
  lines = fp.readlines()
  # move file pointer to the beginning of a file
  fp.seek(0)
  # truncate the file
  fp.truncate()

  # start writing lines except the first line
  # lines[1:] from line 2 to last line
  fp.writelines(lines[1:])
Said Erraoudy
  • 1,490
  • 1
  • 13
  • 21