2

I have a lot of numbered *.csv files with different numbers of lines and just as many *.txt files. I want to append on every line of file 1.csv the content of file 1.txt, on every line of file 2.csv the content of file 2.txt and so on. Each *.txt file contains only one line.

What I have tried:

for i in {1..2}; do for j in {1..2}; do perl -i -p -e "s/^(.+?)$/\1<content of $j.txt>/g" ./$i.csv; done; done

But obviously this doesn't work.

example (initial situation):

1.csv
  line 1
  line 2
  line 3

2.csv
  line 1
  line 2

1.txt
  yyy

2.txt
  zzz

result (should be):

1.csv
  line 1yyy
  line 2yyy
  line 3yyy

2.csv
  line 1zzz
  line 2zzz

1.txt
  yyy

2.txt
  zzz

Any help would be appreciated.

3 Answers 3

2

To expand on your perl attempt, perhaps

for f in ./*.csv; do 
  perl -i -lpe 'BEGIN{$x = shift @ARGV} s/$/$x/' "$(<"${f%.csv}.txt")" "$f"
done

(assuming ksh/zsh/bash for the $(<file) operator; replace with $(cat<file) if your shell doesn't support it).

giving

$ head ./*.csv
==> ./1.csv <==
  line 1yyy
  line 2yyy
  line 3yyy

==> ./2.csv <==
  line 1zzz
  line 2zzz

However you don't really need a regex substitution for this - you could consider replacing s/$/$x/ by a simple string concatenation $_ .= $x

0
1

Use awk:

for f in *.csv; do
    awk '
        FNR==NR{txt=$0}
        FNR!=NR{printf "%s%s\n",$0,txt}
    ' "${f%.*}.txt" "$f" > "$f.csv.tmp" && mv "$f.csv.tmp" "$f"
done

Output:

$ cat a.csv
line 1yyy
line 2yyy
line 3yyy

Some modern implementations of awk have -i inplace option, so you won't need the "tmp and mv part". See here.

0

A sed-oneliner:

for i in 1 2 ; do sed -i "s/$/$(cat $i.txt)/" $i.csv ; done

s/$/ I'm replacing the end of each line, thus appending to the line

$(cat $i.txt) append the text-file named after the current number.

Note that this will will lead to problems if the filen.txt contains special characters like slash, backslash, quotes, ...

If this is a concern, use an ascii record separator instead of the / in the sed-statement. You can type those in vim by pressing Ctrl+V, then enter their decimal value --- 030 in this case

You must log in to answer this question.

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