美文网首页
ZSH 你不知道那些事儿-005-高级通配符

ZSH 你不知道那些事儿-005-高级通配符

作者: FFCP | 来源:发表于2017-08-28 22:14 被阅读295次

    上一篇介绍了 zsh 的 9 种展开和替换,其中也包括基本的通配符。本篇介绍 zsh 独有的通配符标记和通配限定符功能。

    1 通配符标记

    通配符标记的作用是声明通配符的一些额外属性,如是否区分大小写等;通配符通过 (#X) 这种格式指定,其中, X 包括:

    • i 不区分文件名的大小写,示例:

      # 列出全部 .txt 结尾的文件,.txt 部分不区分大小写
      ls -l (#i)*.txt
      
    • I 区分大小写

    • l 智能大小写匹配,即 Globbing 中的小写字母既匹配它自身也匹配它的对应大写字母,而大写字母只匹配它自身。

    • s , e 匹配字符串的开头和结尾,相当于正则表达式中的 ^ / $.

    • cN,M 匹配 N 到 M 个被它修饰的 Globbing,相当于正则表达式中的 {N,M}

    • m 将匹配到的文本写入变量 MATCH 中,示例:

      s='hello 1 world 2 ! 3'
      echo ${s//(#m)<0-9>/$[MATCH*2]}  # 输出:'hello 2 world 4 ! 6'
      

      上例演示了如何将一个字符串中包含的数字都扩大一倍

    • U 禁用多字节字符支持。我们知道 ? 表示匹配任意一个字符,那么在 UTF-8 环境下一个中文字符是需要一个 ? 匹配还是多个 ? 匹配呢?答案是:zsh 默认就支持多字节字符,所以只需要一个 ? 就可以匹配了;某些情况下可能想按照字节处理字符串,而不是按照字符。这个使用可以使用 U, 这种情况下需要 3 个 ? 才能匹配一个 UTF-8 编码的 “中” 字。示例:

      [[ 中文 = (#s)(??)(#e) ]] && echo yes  # => yes
      [[ 中文 = (#s)(??????)(#e) ]] && echo yes  # => nothing
      [[ 中文 = (#u)(#s)(??)(#e) ]] && echo yes  # => yes
      [[ 中文 = (#U)(#s)(??)(#e) ]] && echo yes  # => nothing
      [[ 中文 = (#U)(#s)(??????)(#e) ]] && echo yes  # => yes
      

    2 通配限定符

    可以在整个通配表达式的末尾加上一对圆括号,在圆括号中指定限定符。限定符主要作用是对匹配到文件进行限定过滤或者指定匹配结果的排序规则,zsh 支持的限定符包括:

    • / 只匹配目录,示例:

      # 递归列出当前目录下所有名字中包含 hello 的目录
      print -l **/*hello*(/)
      
    • F 只匹配非空目录

    • . 只匹配普通文件(即非目录文件)

    • @ 只匹配符号链接文件

    • = 只匹配 UNIX Domain Socket 文件

    • p 只匹配命名管道文件

    • * 只匹配可执行的普通文件

    • % 只匹配设备类型文件

    • %b 只匹配块设备文件,如磁盘

    • %c 只匹配字符设备文件,如终端

    • r 对 owner 可读的文件

    • w 对 owner 可写的文件

    • x 对 owner 可执行的文件

    • A 对 group 可读的文件

    • I 对 group 可写的文件

    • E 对 group 可执行的文件

    • R 对 others 可读的文件

    • W 对 others 可写的文件

    • X 对 others 可执行的文件

    • s setuid 文件

    • S setgid 文件

    • t 设置了粘滞位的文件,如 /tmp 目录

    • e:CODE: 每匹配到一个文件会执行 CODE 指定的代码,当前匹配的文件将会设置为变量 REPLY 的值, CODE 中的代码可以应用 REPLY 的值,如果 CODE 的退出状态码为 0 则当前文件会被包含在匹配列表中,否则将不会匹配当前文件

    • dDEV 在设备 DEV 上的文件

    • l[-|+]CT 文件链接数小于 CT(-) 或 大于 CT(+) 或等于 CT

    • a[Mwhms][-|+]N 文件最后访问时间时间早于 N(+) 或晚于 N(-) 或等于 N 个时间单位,时间单位的含义为:

      • M
      • w
      • h 小时
      • m 分钟
      • s

      示例:

      print -l *(a+2)  # 列出所有最后访问时间早于两天前的文件
      print -l *(aw-1) # 列出所有最后访问时间晚于一周前的文件
      print -l *(ah3)  # 列出所有最后访问时间为 3 小时前的文件
      
    • m[Mwhms][-|+]N 文件最后修改时间时间早于 N(+) 或晚于 N(-) 或等于 N 个时间单位

    • c[Mwhms][-|+]N 文件 inode 最后修改时间时间早于 N(+) 或晚于 N(-) 或等于 N 个时间单位

    • L[KMGTP][-|+]N 文件大小小于 N(-) 或 大于 N(+) 或等于 N 个单位

    • ^ 对跟在它后面的 Globbing 取反

    • oC 按照升序对匹配结果进行排序,其中的 C 可以是以下值:

      • n 按名称排序(默认)
      • L 按文件大小排序
      • l 按链接数排序
      • a, m, c 按文件最后访问时间、最后修改时间或 inode 最后修改时间排序
    • OC 倒序(desc)排序

    • [BEG[,END]] 只保留匹配结果的一个子集。

    • N 不让 zsh 在匹配不到任何结果的时候报错

    • D 通配符默认不匹配以 . 开头的文件, D 会取消这个限制。

    • n 当使用文件名排序时,按照数值大小排序而不是字母表顺序。

    2.1 通配限定符示例

    • 递归查找当前目录下坏掉的符号链接(包括隐藏文件)

      file **/*(D@) | fgrep broken
      
    • 按名称降序列出当前目录下的文件

      print -rl -- *(On)
      # or
      print -rl -- *(^on)
      
    • 将当前目录中的 200 个文件移动到另外一个目录

      mv -- *([1,200]) /another/Dir
      
    • 列出所有的 *.c 文件,但是忽略 foo.c

      ls *.c~foo.c
      
    • 删除比指定时间更早的文件

      rm -f /Dir/**/*(.mh+3)   # 删除早于 3 个小时之前的普通文件
      rm -f /Dir/**/*(@mm+3)   # 删除早于 3 分钟之前的符号链接文件
      rm -f /Dir/**/*(ms+30^/) # 删除早于 30 秒之前的非目录类型的文件
      rm ./*(Om[1,-11])        # 删除除最新的 10 个文件外的全部其他文件
      
    • 列出最近 10 个小时未发生过修改的全部非目录类型的文件

      print -rl -- *(Dmh+10^/)
      
    • 打印当前目录下最大的 5 个文件(相当于 ls -laS | head -n 5

      ls -fl *(DOL[1,5])
      
    • 列出全部的非空目录

      ls -ld *(/^F)
      

    相关文章

      网友评论

          本文标题:ZSH 你不知道那些事儿-005-高级通配符

          本文链接:https://www.haomeiwen.com/subject/jykndxtx.html