views:

229

answers:

3

How to get a list of files that match some pattern if filenames may contain \n character?

Update: I want solution in pure vimscript, so that it will depend on nothing but vim.

Update2:

Expected output of glob function

Consider the following script:

:!touch /test ; mkdir /test$'\n' ; touch /test$'\n'/test
:echo glob('/**/test')
/test
/test
/test

That is the output of glob function. I want it be the following:

:echo NewGlob('/**/test')
['/test', '/test
/test']
A: 

Try this python program. It will match files like abc\n1, abc\n2abc etc.

#!/usr/bin/env python
import os, re
dirlist = os.listdir('.')
pattern = 'abc\n\\d'
for fname in dirlist:
  if re.search(pattern, fname):
    print fname.replace('\n', '\\n')

It will replace line end ('\n') characters with "\n" string for clarity.

Paweł
+1  A: 

you may try using ls with -b option. check the man page

ghostdog74
I can also use `find -print0`, but I can't rely on existence of `ls` or `find`. And `ls -Q` is more suitable in this case.
ZyX
+1  A: 
:echo split( glob("pattern", '.'), "\r")

If you want the pattern to match files containing \n exclusively, use "*\n*".


EDIT:

I see, the character you use in the filename is the same as the one used by glob() to distinguish results. As a consequence, we can't rely of glob(). ghostdog74 gave a good answer then:

:echo split( system('ls -1bd test*'), "\n")  

Of course, this is not portable. But I do not really call this the general case -- I never see this kind of names. If glob() cannot handle this general case, then glob() must be fixed.

May be you can try with embedded python or ruby as arnold suggested. But that isn't portable either.

Luc Hermitte
No, I want to construct a generic `glob` function that will take any pattern that glob accepts (excluding `glob("\x60command\x60")`) and return a list of files, that all match specified pattern and all exist. Since the function is generic, I must consider the case when there is LF in filename. Now I can only do that thing: convert glob pattern into string pattern, split glob on LF and join until I get a unique filename that both matches this string pattern and exists (no code, only an idea that I do not like).
ZyX
I fail to understand the problem. Could you elaborate your need? i.e. the "newglobfunction" call + the expected output?
Luc Hermitte
@Luc Hermitte Updated.
ZyX
@Luc, glob can't really be "fixed" -- it is specified to return a string with new-line delimiters between filenames. A NewGlob function could of course have a different specification to return an array, just as ZyX wants. (I'm in fact surprised that vim's glob throws away useful information just for some convenience; an array of filenames can easily be turned into a nl or space delimited string, but the reverse is very difficult.)
sarnold
|List|s were not implemented at the time `glob()` was added to vim. So indeed, we'd need a `globreturnedaslist()` function to avoid any regression.
Luc Hermitte
Not the answer I was looking for, but bounty ends in 2 hours and this is the best answer given.
ZyX