【问题标题】:How to get a list of files that match some pattern?如何获取与某种模式匹配的文件列表?
【发布时间】:2011-03-08 14:31:57
【问题描述】:

如果文件名可能包含\n 字符,如何获取与某些模式匹配的文件列表?

更新:我想要纯 vimscript 中的解决方案,这样它就只依赖于 vim。

更新2

glob 函数的预期输出

考虑以下脚本:

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

这是glob函数的输出。我希望它是以下内容:

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

【问题讨论】:

  • 我在 vim 文档中没有找到任何可以提供你想要的东西的东西,也没有找到任何目录列表工具,除了 :browse。但是 vim 通常被构建为链接到 Perl、Python 或 Ruby 以提供更多的库/功能。这样可以吗?

标签: linux unix filenames vim


【解决方案1】:

您可以尝试将ls-b 选项一起使用。检查手册页

【讨论】:

  • 我也可以使用find -print0,但我不能依赖lsfind 的存在。而ls -Q更适合这种情况。
【解决方案2】:
:echo split( glob("pattern", '.'), "\r")

如果您希望该模式仅匹配包含 \n 的文件,请使用 "*\n*"


编辑:

我明白了,您在文件名中使用的字符与glob() 用于区分结果的字符相同。因此,我们不能依赖glob()。 ghostdog74 给了good answer 然后:

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

当然,这不是便携式的。但我并没有真正将其称为一般情况——我从未见过这种名字。如果glob() 无法处理这种一般情况,则必须修复glob()

也许您可以按照阿诺德的建议尝试使用嵌入式 python 或 ruby​​。但这也不便携。

【讨论】:

  • 不,我想构造一个通用的glob 函数,它将采用glob 接受的任何模式(不包括glob("\x60command\x60"))并返回一个文件列表,这些文件都匹配指定的模式并且都存在。由于该函数是通用的,因此我必须考虑文件名中有 LF 的情况。现在我只能做那件事:将 glob 模式转换为字符串模式,在 LF 上拆分 glob 并加入,直到我得到一个与此字符串模式匹配且存在的唯一文件名(没有代码,只有我不喜欢的想法)。
  • 我无法理解问题所在。你能详细说明你的需求吗?即“newglobfunction”调用+预期输出?
  • @Luc,glob 不能真正被“固定”——它被指定返回一个文件名之间带有换行符的字符串。 NewGlob 函数当然可以有不同的规范来返回一个数组,就像 ZyX 想要的那样。 (事实上​​,我很惊讶 vim 的 glob 只是为了方便而丢弃了有用的信息;文件名数组可以很容易地转换为 nl 或空格分隔的字符串,但反过来非常困难。)
  • |List|s 在glob() 添加到 vim 时没有实现。所以确实,我们需要一个globreturnedaslist() 函数来避免任何回归。
  • 不是我要找的答案,但赏金会在 2 小时后结束,这是给出的最佳答案。
【解决方案3】:

试试这个 python 程序。它将匹配abc\n1abc\n2abc 等文件。

#!/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')

为了清楚起见,它将用“\n”字符串替换行尾('\n')字符。

【讨论】:

    【解决方案4】:

    我最后不得不编写以下函数,它返回与 python 的 os.listdir 相同的结果:

        function s:globdir(directory, ...)
            return split(glob(escape(a:directory.g:os#pathSeparator, '`*[]\').
                        \     get(a:000, 0, '*')),
                        \"\n", 1)
        endfunction
        function s:GetDirContents(directory)
            let dirlist = s:globdir(a:directory)+s:globdir(a:directory, '.*')
            let nlnum=len(split(a:directory, "\n", 1))-1
            let r=[]
            let i=0
            let addfragment=""
            for directory in dirlist
                if i<nlnum
                    let i+=1
                    let addfragment=directory."\n"
                    continue
                else
                    let directory=addfragment.directory
                    let i=0
                    let addfragment=""
                endif
                let tail=fnamemodify(directory, ':t')
                if tail==#'.' || tail==#'..'
                    continue
                endif
                if directory[0]!=#'/'
                    let r[-1].="\n".directory
                else
                    call add(r, tail)
                endif
            endfor
            return r
        endfunction
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-18
      • 2011-11-22
      • 1970-01-01
      • 2012-01-21
      • 2010-10-05
      相关资源
      最近更新 更多