I am creating 22 files with this following command:

user@host$ awk '{ print $1, $3, $4, $5 }' chr22.gen > snps22
user@host$ awk '{ print $1, $3, $4, $5 }' chr21.gen > snps21
user@host$ awk '{ print $1, $3, $4, $5 }' chr1.gen > snps1

The output files look as follows:

user@host$ head snps21
rs885550 9887804 C T
rs169757 9928594 A C
rs210498 9928860 C T
rs210499 9929079 C A
rs303304 9941889 A G

What I would like to do is to modify these output files (snps22, snps21, snps20 ...) such that snps21 e.g. looks like this:

user@host$ head snps21
rs885550 21:9887804:C:T
rs169757 21:9928594:A:C
rs210498 21:9928860:C:T
rs210499 21:9929079:C:A
rs303304 21:9941889:A:G

So it is needed to join the number from the name of the input file, chr21.gen (which is 21) to the 2nd column of the output file with a colon and then join with a colon the 2nd, 3rd and 4th column.


2 Answers 2


Assuming that your files are called exactly as you've shown, i.e. the string snps followed by the chromosome name, then you may use

for name in snps*; do
    awk 'FNR == 1 { chr = substr(FILENAME, 5) }
         { printf("%s %s:%s:%s:%s\n", $1, chr, $2, $3, $4) }' "$name" >"$name.new"

This extracts the chromosome name from the filename by means of substr() (the chromosome name is all characters in the filename from character five onwards). This is only done when reading the first line of the file (FNR == 1). The code then outputs the current line on the format wanted using printf(), incorporating the chromosome name.

The data is then written to files with a .new filename suffix.

The shell loop can be done away with by letting awk choose where to write the output:

awk 'FNR == 1 { chr = substr(FILENAME, 5); name = FILENAME ".new" }
     { printf("%s %s:%s:%s:%s\n", $1, chr, $2, $3, $4) >name }' snps* 

Would you want to collect all output in a single file, it would be enough with

awk 'FNR == 1 { chr = substr(FILENAME, 5) }
     { printf("%s %s:%s:%s:%s\n", $1, chr, $2, $3, $4) }' snps* >all_snps

You could also apply a modified variant to the original .gen files that you had:

awk 'FNR == 1 { chr = substr(FILENAME, 4); sub("\.gen$", "", chr)
                name = "snps" chr }
     { printf("%s %s:%s:%s:%s\n", $1, chr, $3, $4, $5) >name }' chr*.gen

or, for a single output file,

awk 'FNR == 1 { chr = substr(FILENAME, 4); sub("\.gen$", "", chr) }
     { printf("%s %s:%s:%s:%s\n", $1, chr, $3, $4, $5) }' chr*.gen >all_snps

This is just a matter of picking slightly different columns from the data, and having to extract another part of the filename to find the name of the chromosome.

  • You could probably make the examples where you loop externally over the input files more efficient by using awk's output redirection functions, as in print ... > output_filename: Since you are using the FILENAME internal variable anyway to extract the "serial number", you could also use it to generate individual output filenames for each input file.
    – AdminBee
    Commented Apr 28, 2020 at 8:00
  • 1
    @AdminBee Yes, but that would make for slightly more complicated awk code. I will add it as an alternative anyway. Thanks.
    – Kusalananda
    Commented Apr 28, 2020 at 8:02

Quick attempt using bash (and sed and tr) :

for i in snps* 
  n=$(echo $i |tr -d 'a-zA-Z')
  sed -i -e "s/ / $n:/" -e 's/ \([A-Z]\)/:\1/g' $i

This just loops through the set of files starting with snps2, and for each file it strips all alphabetic characters from the name to obtain the numeric part, then uses sed to (a) replace the first space with a space, the numeric part of the filename, and a colon, and (b) replaces every space followed by an uppercase letter with a colon. I am pretty sure it could be done equally well using awk instead.

  • Hi Jonathan thanks for this I do have 22 files and their names are snps1, snps2, snps3..snps22. Can you please edit your script so that it works for that. Would for i in snps* do it?
    – anamaria
    Commented Apr 28, 2020 at 1:59
  • Yes, absolutely. Let me know if that works for you, and if it does, please mark my answer as correct. Commented Apr 28, 2020 at 2:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .