Using Vim 8.0

I'm trying to make a table where the first column is the name of a file and the second column the creation date of such file, to which I have access by the exif data.

I would like to achieve this in one line, just to learn how.

Currently, I'm using:


To get all the filenames I'll be working with. (If I want to filter .pdf files from this, how can I grep them out?)

Then, I would like to run something like this:

:read !exif -t 0x9003 -m

(which writes the date in the next line) but having the output append to the same line where the filename is, leaving a space or comma to separate the columns.

Was thinking that maybe I should write the ouput of !exif -t 0x9003 -m to a register @a and then use :normal $a<C-R>a to append it, but, again, failed to figure out how to do that.

Another idea was to use :execute ':normal A ' . "foo" ,this almost works, but cannot figure out a way to use the output of exif instead of "foo".

Thank you very much.

3 Answers 3


There are two ways to approach this. Go heavy on the Vim or do what a rational person would do in the real world: lean heavily on the shell and let it do all the work as that's its strength. Though this is Vi/Vim SE I'm going to be contrarian and show the practical solution. ;)

Let's say you use Bash and you want to run exif on all PNG files in a certain directory. One way is:

for f in ~/images/*.png; do
    printf "%s : %s\n" "$f" "$(exif -t XXX -m "$f")"

The key to this one is the "process substitution" feature $(exif -t XXX -m "$f"). You'll get each PNG file name followed by a : and then the exif command output for that file.

You can just cram that all on a Vim command line like this:

:r !for f in ~/images/*.png; do printf "\%s : \%s\n" "$f" "$(exif "$f")"; done

(Note that you have to escape % here as otherwise Vim interprets them as special characters.)

Or you can put those shell commands in a script and just do:

:r !myscript.sh

BTW, if you want to loop over all files in a dir except PDFs then you can use for f in ~/images/*.!(pdf) but you'll need to first enable that syntax with shopt -s extglob.


Since the bulk of the action is happening on external commands here, using a shell script is probably most appropriate in this particular case.

If you do want to execute this inside Vim, then using the system() function is a great way to execute an external command and get the result into a string. (You can then use trim() to remove the trailing newline. You can also use shellescape() to escape filenames to safely pass them as arguments to the external command.)

To modify lines in place, I'd recommend using a :s command, in particular using \= in the replacement part to use the result of a Vimscript expression as the replacement. You can then use submatch(0) to access the original matched text.

Finally, you can use :v to exclude the lines which have filenames with the .pdf extension.

Putting it all together:

:v/\.pdf$/s/.\+/\=submatch(0)."\t".trim(system("exif -t 0x9003 -m ".shellescape(submatch(0))))

This will append the EXIF info to the lines with the filenames, using a Tab character as a separator.

Assumes your input was acquired with :0read !ls or similar, the buffer has a list of filenames to handle. Empty lines will be skipped by the .\+ match, so they're ok too.


What about using regular setline and getline functions?

call setline('.', getline('.') .. "NEW ADDITION")

Couple it with systemlist function:

call setline('.', getline('.') .. systemlist('date')[0])

You will add output of the system date to the current line.

I don't have exif so this is for you to check:

nnoremap <space>d :call setline('.', getline('.') .. systemlist('exif -t -m ' .. getline('.'))[0])<CR>

Press <space>d to add output of your exif to current line.

Or you can use it with :g command for all files in a buffer:

:g/^/call setline('.', getline('.') .. systemlist('exif -t -m ' .. getline('.'))[0])

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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