7

I have lots of CSV files and I need the filename of each specific CSV file in every line of each file.

Original file content of abc123.csv:

ColVal_1;ColVal_2;ColVal_3
ColVal_4;ColVal_5;ColVal_6

New file content:

ColVal_1;ColVal_3;ColVal_3;abc123.csv
ColVal_4;ColVal_5;ColVal_6;abc123.csv

All CSV files are in the same directory. I don't want to specify the name of each file.

4 Answers 4

5

Its much more simple, easier and faster with sed and xargs. Here sed uses in-place editing thus avoiding additional shell tools.

$ ls file{1..5}.txt|xargs -I% sed -i 's/$/;%/' %

And here is the output.

$ cat file{1..5}.txt
ColVal_1;ColVal_2;ColVal_3;file1.txt
ColVal_4;ColVal_5;ColVal_6;file1.txt
ColVal_1;ColVal_2;ColVal_3;file2.txt
ColVal_4;ColVal_5;ColVal_6;file2.txt
ColVal_1;ColVal_2;ColVal_3;file3.txt
ColVal_4;ColVal_5;ColVal_6;file3.txt
ColVal_1;ColVal_2;ColVal_3;file4.txt
ColVal_4;ColVal_5;ColVal_6;file4.txt
ColVal_1;ColVal_2;ColVal_3;file5.txt
ColVal_4;ColVal_5;ColVal_6;file5.txt
3

Using sed you can do something like,

for f in *.csv
do
 sed -i 's/$/ '"$f"'/' "$f"
done

Testing

Inside one of the directories, I created couple of csv files.

cat csv1.csv

this
is
first
csv
file

##Second CSV file

cat csv2.csv

this
is
second
csv
file

Now, I executed the above command that I had mentioned. After the execution of the command, the files look like below.

cat csv1.csv

this csv1.csv
is csv1.csv
first csv1.csv
csv csv1.csv
file csv1.csv

##Second CSV file

cat csv2.csv

this csv2.csv
is csv2.csv
second csv2.csv
csv csv2.csv
file csv2.csv

If you want semicolons you can just add it in the sed command before appending the file name. Change the sed command like below.

 sed -i 's/$/ '";$f"'/' "$f"

References

http://www.unix.com/unix-for-dummies-questions-and-answers/150545-merge-files-add-file-name-end-each-line.html

3
  • @Gnouc, Thanks for the edit. However, without double quotes it worked fine in my machine. :)
    – Ramesh
    Commented Jun 25, 2014 at 17:07
  • We need double quotes with file name contains special characters.
    – cuonglm
    Commented Jun 25, 2014 at 17:09
  • @Gnouc, ok that makes sense. Thanks for the info :)
    – Ramesh
    Commented Jun 25, 2014 at 17:10
0

How about:-

for i in *.csv; do awk '{print $0 ";" FILENAME }' $i > ${i}.tmp ; mv ${i}.tmp ${i} ; done

You could avoid the mv if you have a later version of awk but this is probably more portable.

3
  • That's almost the solution, but this statements appends a line break and the filename for each line.
    – AvS
    Commented Jun 25, 2014 at 15:10
  • That's peculiar - it doesn't add a line break on my system! I get:- ColVal_1;ColVal_2;ColVal3;abc123.csv ColVal_4;ColVal_5;ColVal6;abc123.csv` As two seperate lines (I can't get that to display here!) Commented Jun 25, 2014 at 15:16
  • I've ran this on both an Ubuntu 14.04 and a Fedora 20 system and both produce the correct result. What system are you running? Commented Jun 25, 2014 at 17:53
0

With perl:

$ perl -i.bak -ple '$_ .= ";"$ARGV' file.csv 
ColVal_1;ColVal_2;ColVal_3;file.csv
ColVal_4;ColVal_5;ColVal_6;file.csv

From perldoc -v '$ARGV':

$ARGV   Contains the name of the current file when reading from "<>".

You can use *.csv to process all files in current directory. -i.bak option edit all files inplace and create backup files with name *.csv.bak.

You must log in to answer this question.

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