1

I am trying to add a few headers to occasionally empty CSV file (so sometimes the file will be empty and sometimes it will have data) via bash. So far I have tried using sed and awk.

Sed:

sed -i '1liAge,Sex,Location' $nameOfFile

Awk:

awk 'BEGIN{print "Age,Sex,Location"}1' $nameOfFile

Both of these do not appear to work since no headers are added. When I echo $nameOfFile, csvInfo.csv is printed so I don't believe there's anything wrong with $nameOfFile. Not sure where i'm going wrong here.

Brandon Hu
  • 93
  • 6
  • `printf '%s\n' '0a' "Age,Sex,Location" . %p Q | ed -s "$nameOfFile"` – Jetchisel Aug 16 '21 at 22:55
  • 1
    If it's an empty file, `echo header1,header2,etc. > file.csv`? – Shawn Aug 16 '21 at 22:57
  • If it has no lines, the sed command won't work (if it is even valid - what is `li`?). The awk command doesn't overwrite the original. Not entirely sure what you mean by "an empty CSV file". If it is empty, why not just echo the headers into it? – jhnc Aug 16 '21 at 22:58
  • @jhnc The file won't always be empty. Sometimes it'll have data in it and sometimes it won't so i'm trying to make it work for both scenarios. – Brandon Hu Aug 17 '21 at 03:08
  • @Jetchisel That is printing to console but I want to write (modify) the CSV file. – Brandon Hu Aug 17 '21 at 03:17
  • @BrandonHu, change `Q` to `w` to edit the file, also remove the `%p` if you don't want to see the output. – Jetchisel Aug 17 '21 at 05:19
  • @BrandonHu : If a file is **empty**, we can't say it is a CSV-file; an empty file does not have any property. Actually, inserting something in the middle of a text file can't really be done "in place" (think how you woul program this in, say, C!), so you create a new file, and if you were successful, you move the new file over the old one. – user1934428 Aug 17 '21 at 06:40

1 Answers1

2

Your sed command requires there to already be at least one line in the file, so I don't think you can make that work reliably.

The Awk command you have should work as such, but it writes its results to standard output. If you have GNU Awk, you can use -i inplace to get behavior similar to sed -i; but the portable solution is to write the results to a temporary file, then move back on top of the old file.

awk 'BEGIN{print "Age,Sex,Location"}1' "$nameOfFile" >tmp
mv tmp "$nameOfFile"

Notice also When to wrap quotes around a shell variable.

If you want to avoid adding a header when it's already there, you can keep the BEGIN block, but suppress printing of the old header, if present:

awk 'BEGIN{print "Age,Sex,Location"}
    NR>1 || $0 !~ /^Age,Sex,Location$/' "$nameOfFile" >tmp
mv tmp "$nameOfFile"

Proper hygiene around temporary files is somewhat more involved for a production script, but if this is just for your personal use, let's leave it at this. For more information, perhaps review Removing created temp files in unexpected bash exit

tripleee
  • 175,061
  • 34
  • 275
  • 318