Search code examples
linuxbashshellopenwrt

Linux: Extract the first line of a file


I am working with OpenWrt and a very small amount of space.

Trying to extract the first line from a file. The line needs to go into a variable and be removed from the file. I can use head to put it into a variable but can't use tail because as far as I understand I would have to do tail file > newFile and I do not have room for that second file.

Does some one know if a better technic?


Solution

  • Edit: you can't use my old answer (see below) with OpenWrt since OpenWrt doesn't ship with ed. What a shame. So here are two methods:

    The vi way

    vi is a genuine editor too, so the following will work:

    vi -c ':1d' -c ':wq' file > /dev/null
    

    We open the file with vi, and use the commands :1d to delete the first line and :wq to save and quit, redirecting all output to /dev/null. Cool, clean, short and simple.

    Oh, you will of course run:

    firstline=$(head -n1 file)
    

    before running this vi command to get the first line of the file into the variable firstline.

    Note. On a system with very little memory, and when file is huge, this method fails.

    The dd way

    dd is a cool tool for this. The dd methods given in other answers are really great, yet they rely on the truncate utility which does not ship with OpenWrt. Here's a workaround:

    firstline=$(head -n1 file)
    linelength=$(head -n1 file | wc -c)
    newsize=$(( $(wc -c < file) - $linelength ))
    dd if=file of=file bs=1 skip=$linelength conv=notrunc
    dd if=/dev/null of=file bs=1 count=0 seek=$newsize
    

    This will work even with huge files and very little memory! The last dd command plays the role of the truncate command given in the other answers.


    Old answer was:

    You can use ed for this:

    firstline=$(printf '%s\n' 1p d wq | ed -s file.txt)
    

    At each call, you'll get the first line of the file file.txt in the variable firstline, and this line is removed from the file.