查找包含数字的文件名

查找包含数字的文件名

我想找到包含数字的文件名并将它们列出在数字范围内。例如,在我的目录中有:**

Ion_001_rawlib.bam
Ion_002_rawlib.bam
Ion_003_rawlib.bam
Ion_004_rawlib.bam
Ion_005_rawlib.bam
...
Ion_020_rawlib.bam

**

我只想列出从 003 到 005 的 Ion 文件名。我尝试这样做:

find -name '*Ion_*[3-5]*rawlib.bam'

但并没有产生预期的效果。您知道是否可以执行吗?谢谢。

答案1

使用zshshell,您可以执行以下操作:

print -rC1 Ion_<3-5>_rawlib.bam

其中是一个全局运算符,它匹配给定范围(从到,包括)<x-y>内的正整数的文本十进制表示形式。xy

递归地:

print -rC1 -- **/Ion_<3-5>_rawlib.bam

(D)如果您还想在隐藏文件夹中查找这些文件,或者(N)如果您不想在没有匹配文件时将其视为错误,请添加)。

通过find支持-regex谓词的实现,您可以执行以下操作:

LC_ALL=C find . -regex '.*/Ion_0*[345]_rawlib\.bam'

(匹配包含 0 个或多个 ( *) 字节(.带有LC_ALL=C)、后跟/Ion_0 个或多个 ( *) 0、后跟345字符之一的文件路径,后跟rawlib.bam)。

在这里,对于 3..5 范围来说相对容易,但是对于像 78..123 这样的范围来说会变得更加痛苦(并且您会遇到兼容性问题,因为find支持-regex使用不同格式的正则表达式的少数实现) )。

标准find仅支持-name-path用于匹配文件名,它是使用基本的 shell 通配符而不是正则表达式来完成的,但通配符没有相当于*regexp 运算符(0 个或多个前面的原子),其*运算符相当于 regexp .*(0 个或多个字符),因此Ion_*[3-5]_rawlib.bam将匹配 onIon_9994_rawlib.bam例如作为*匹配 on 999

然而,在这个简单的情况下,您可以使用多种模式和否定来完成此操作,例如:

LC_ALL=C find . -name 'Ion_*[345]_rawlib.bam' \
              ! -name 'Ion_*[!0]*?_rawlib.bam'

非递归:

LC_ALL=C find . ! -name . -prune \
    -name 'Ion_*[345]_rawlib.bam' \
  ! -name 'Ion_*[!0]*?_rawlib.bam'

要查找名称中任意位置包含整数十进制表示形式的文件,您需要一个与该范围匹配的模式(如xs ),但还要确保该模式不被其他数字包围。例如确实包含、和,所有这些都匹配。yzsh<x-y>foo305.txt3055<3-5>

在 中zsh,那就是:

print -rC1 -- (|*[^0-9])<3-5>(|[^0-9]*)

也就是说<3-5>(匹配 3, 03, 003...),后面紧跟任何内容或以非数字结尾的字符串,后面紧跟任何内容或以非数字开头的字符串。

使用BSD find

LC_ALL=C find -E . -regex '.*/([^/]*[^0-9])?0*[3-5]([^0-9][^/]*)?'

与 GNUfind相同,但替换-E .. -regextype posix-extended.

使用 busybox find(尽管取决于它的编译方式):

busybox find . -regex '.*/\([^/]*[^0-9]\)\?0*[3-5]\([^0-9][^/]*\)\?'

另一种方法是使用find报告文件列表,但使用更高级的语言,例如perl过滤该列表:

find . -print0 | perl -l -0ne '
  if (m{[^/]*\z}) {
    for $n ($& =~ /\d+/g) {
      if ($n >= 3 && $n <= 5) {
        print;
        next LINE;
      }
    }
  }'

此处,用于perl从每个文件的基本名称中提取所有十进制数字序列,如果这些数字序列中至少有一个表示 3..5 范围内的数字,则输出文件。

相关内容