0

I have a template A.tsv (field separator =\t) :

Name    data

And several file , for example B.txt and C.txt.

I want to print the filename in the filename (but in a new file) like this :

Name    data
B
C

I've done this :

template="A.tsv"
for bla in data/*.txt ; do
r="$(basename -s ".txt" $bla)"
( head -n 1 $template
awk -F'\t' -v OFS="\t" -v filename=$r '{print filename}' $bla ) > test_name.tsv  ;
done

But it give me :

Name    data
C
C
C
C
C
C
C

Do you have a clue on wht's wrong with my command ?

Thanks

2
  • awk will execute your command once per line of the file. So you repeatedly make awk print the variable $r, hence the many "C"s. Why do you use awk in the first place? Use >> file to append output to a file (where > file would overwrite the file) and directly write basename's results.
    – FelixJN
    Jan 20, 2021 at 8:33
  • I did'nt fully understand your solution ? What can I change aside from > to >> ?
    – nstatam
    Jan 20, 2021 at 8:39

1 Answer 1

0

A script with detailed comments:

#!/bin/bash

#using the template variable is redundant, but
#I assume you want to use that lateron
template="A.tsv"
#write header from template and create file "output.txt"
#overwrites old version of "output.txt" if existing
head -n 1 ${template} > output.txt

#loop over files:
for bla in data/*.txt ; do
   #get basename without file suffix, add result to "output.txt" 
   basename -s ".txt" ${bla} >> output.txt
done

Note that you should prefer using ${variable} or "$varaible", especially for filenames, otherwise the script will break in case of files with e.g. spaces in the name.


Why did the awk-approach fail?

awk runs on a per-line basis. Your code had this:

awk -v variable=$r '{print variable}' ${file}

So when you have a file with 10 lines, the above command will be executed 10 times and result in 10 lines of the variable. For stopping awk after one run, use exit or specify a line where the command should be executed:

#execute command only on line no. 1
awk 'NR == 1 { print $1 }' file
#execute command and quit awk
awk '{ print 1 ; exit }'

Where else did the original script fail?

>> will append the output to a file, where > overwrites it. In your script you had a loop with this content:

( head -n 1 $template
awk [...] $bla ) > test_name.tsv

What happened is that for every match in data/*txt, this command would run, thus overwriting previous versions of test_name.tsv and leaving you with the last run only. Note how you also rewrote the header in every run of the loop.

1
  • Thank you for your solution and for the detail on what I was wrong !
    – nstatam
    Jan 20, 2021 at 9:38

You must log in to answer this question.

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