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.

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

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.