views:

544

answers:

4

Hi folks,

I have a number of text files (700+) and I need to get each file's name into the start of every line in the file.

Example, for filename myfile0072.txt

mike   160
jane   174

to

myfile0072.txt mike 160
myfile0072.txt jane 174

I don't have access to bash or c or perl or anything at work. Is there something I can do in vim to get that results?

Cheers,

Tommy

+2  A: 

How about

:g/^/pu!%
:g/^/j

to insert the filename at the beginning of each line in the current file. To run this over many files, look into argdo or bufdo.

jleedev
Hey jleedev, I gave this a try and it worked nicely! I had to add a few lines to remove the directory part of the filename but it wasn't a problem.qq -> start macro called q:g/^/pu!%:g/^/j:%s/blahhh/blahhhhhh -> remove directory:w -> save file:bn -> move to next files that's open in my vim q -> stop the macro200@q -> run macro q 200 times
Tommy O'Dell
Glad it worked :)
jleedev
+1  A: 

The most simple option is

:%s:^:myfile0072.txt:

Explanation: :: command, %: for every line, s:^:xxx:: Replace the "start of line" with "xxx". I'm not aware that you have some kind of variable substitution, though. But you can use <Ctrl-R>% (which expands to the current filename).

But for 700 files, this seems to be very tedious. I'm wondering about your comment "I have no bash". You must have some kind of shell or you couldn't start vi.

Aaron Digulla
You can also do: `:%s:^:<C-R>%:` if you're in the right directory (`<C-R>%` pulls the current filename into the command line). This could then be used in a mapping.
Al
I already wrote that but SO interpreted `<Ctrl-R>` as an HTML tag :(
Aaron Digulla
Ah yes... `<kbd>Ctrl</kbd>-<kbd>R</kbd>` is one (rather verbose) way round that.
Al
+6  A: 

There are two stages to this, firstly get all the files you want to edit into the argument list, then add the filename to the lines.

1) Add files to argument list.

Either start vim with "gvim *.txt" (if your shell can handle 700 files listed on the command line) or, load gvim with no files open (so the argument list is empty) and then:

cd /path/to/files
" Get the list of files
let filelist = glob('*.txt')
" Add files to the argument list
for file in split(filelist, '\n')
    exe 'argadd ' . file
endfor

2) Do the required filtering on all files:

:argdo %s/^/\=expand('%:t') . ' '/ | w

Explanation:

argdo runs the command on every file in the argument list.

%s/FROM/TO/ replaces FROM with TO

^ is the start of the line (so the replacement adds TO to the start of the line)

\= means that TO should be the result of an expression

expand('%:t') gives the name of the current file (%), only including the tail (':t'), so no leading directory name.

. ' ' appends a space.

| is the command joining character, so after the substitution, it runs:

w, which writes the file to disk.

Al
excellent explanation, +1
rampion
@rampion: Thank you!
Al
A: 

I went with as jleedev suggested since it was most familiar to me

:g/^/pu!%
:g/^/j

For some reason, with multi files open in vim, pu!% made the directory structure come into the file as well. No biggie.

I opened 200 files with the same instance of vim then did this...

qm

'q' to start recording a macro named 'm.

:g/^/pu!% 
:g/^/j 
:%s/blahhh/blahhhhhh 
:w 
:bn

the blahh stuff replaces the directory with blank, :w saves the files and :bn moves to the next file

q

q to end the macro

200@m

200@m means repeat macro m 200 times (because I had 200 files open)

I just did 4 times to get through all of my ~700 files.

Thanks for the help everyone!

Tommy O'Dell
Oh yeah, `%` bases the filename on the current working directory. I think the `autochdir` option will fix that for you.
jleedev