tags:

views:

770

answers:

6

I need to do the following for hundreds of files: Append the name of the file (which may contain spaces) to the end of each line in the file.

It seems to me there should be some way to do this:

sed -e 's/$/FILENAME/' *

where FILENAME represents the name of the current file. Is there a sed variable representing the current filename? Or does anyone have a different solution using bash, awk, etc.?

+4  A: 

You could do it with a bash script

for i in * 
do
  sed -e "s/\$/$i/" "$i" 
done

One-liner version:

for i in * ; do sed -e "s/\$/$i/" "$i" ; done

Edit: If you want to replace the contents of the file with the new, name-appended lines, do this:

TFILE=`mktemp`
for i in * 
do
  sed -e "s/\$/$i/" "$i" > $TFILE
  cp -f $TFILE "$i"
done
rm -f $TFILE
Tyler McHenry
You need quotes around all filename variables for this to work with files that contains spaces as the OP required.
Robert Gamble
For things like this, rather than using mktemp, I'll use "TFILE=tmp.$$". "$$" is the PID, so it's going to be unique. Just a stylistic difference.
Paul Tomblin
Just use the -i option to sed to edit in place.
Steve Baker
-i is a feature of gnu sed
hop
A: 

In BASH, I'd do something to the effect of:

for f in *; do echo $f >> $f; done
ayaz
That will append the name of the file to the end of the file, but not to the end of each line.
Tyler McHenry
i think that only adds the filename to the end of the file, not each line?
warren
OK, terribly sorry. Misread the question.
ayaz
+4  A: 

Some versions of sed support the "--in-place" argument so you can condense Tyler's solution to

for i in * ; do 
  sed -e "s/\$/$i/" --in-place "$i" 
done
Paul Tomblin
Good suggestion. I'm not a sed expert as you can see. :)However you do need a linebreak (or a semi-colon) between the * and the do.
Tyler McHenry
And of course when I typed it into a bash shell to test it, I had the semi-colon.
Paul Tomblin
+7  A: 

I'm sure there are other ways to do it, I'd use perl:

perl -p -i -e 's/$/$ARGV/;' *
shmuelp
Nice! Though it only worked if I separated the options and did perl -pi -e instead of perl -pie.
MCS
@MCS - thanks for the heads-up; I fixed the code sample.
shmuelp
-pie won't work, because -i takes an optional argument. -pei or -epi should work OTOH.
Leon Timmermans
A: 

More or less how Tyler suggested, just with some modifications to allow for spaces in the name. I was hoping for a one-liner though...

(
  OLDIFS=$IFS
  IFS=$'\n'
  for f in *
  do
    IFS=OLDIFS
    sed -e "s/\$/$f/" $f > tmpfile
    mv tmpfile $f
    IFS=$'\n'
  done
)
MCS
If you're willing to use perl, my answer above hits it in 25 characters.
shmuelp
Don't mess with IFS: use "$f" (in double quotes) for each reference.
Jonathan Leffler
+2  A: 

awk '{print $0,FILENAME}' > tmpfile