AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 674938
Accepted
Teatree
Teatree
Asked: 2021-10-27 22:31:57 +0800 CST2021-10-27 22:31:57 +0800 CST 2021-10-27 22:31:57 +0800 CST

查找:使用正则表达式获取路径中具有特定目录名称但路径中没有另一个特定目录名称的所有文件

  • 772

我正在尝试使用 find 返回在其路径中具有特定目录但在文件路径中的任何位置都没有另一个特定目录的所有文件名。就像是:

myRegex= <regex> 
targetDir= <source directory>
find $targetDir -regex $myRegex -print

我知道我也可以通过将一个 find 命令传递到另一个命令来做到这一点,但我想知道如何使用单个正则表达式来做到这一点。

例如,我希望每个文件的路径中都有目录“好”,但无论组合如何,在其路径中的任何地方都没有目录“坏”。一些例子:

/good/file_I_want.txt #Captured
/good/bad/file_I_dont_want.txt #Not captured

/dir1/good/file_I_want.txt #Captured
/dir2/good/bad/file_I_dont_want.txt #Not captured

/dir1/good/dir2/file_I_want.txt #Captured
/dir1/good/dir2/bad/file_I_want.txt #Not captured

/bad/dir1/good/file_I_dont_want.txt #Not captured

请记住,某些文件名可能包含“好”或“坏”,但我只想说明目录名称。

/good/bad.txt #Captured
/bad/good.txt #Not captured

我的研究表明我应该使用 Negative Lookahead 和 Negative Lookbehind。但是,到目前为止,我尝试过的任何方法都没有奏效。一些帮助将不胜感激。谢谢。

find command-line
  • 3 3 个回答
  • 4364 Views

3 个回答

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2021-10-27T23:07:43+08:002021-10-27T23:07:43+08:00

    正如 Inian 所说,您不需要-regex(这是非标准的,并且支持-regex¹的实现之间的语法差异很大)。

    您可以使用-path它,但您也可以告诉find不要输入名为 的目录bad,这比发现其中的每个文件以便以后使用过滤掉它们更有效-path:

    LC_ALL=C find . -name bad -prune -o -path '*/good/*.txt' -type f -print
    

    (LC_ALL=Csofind的*通配符不会阻塞字节序列在区域设置中不形成有效字符的文件名)。

    或者对于多个文件夹名称:

    LC_ALL=C find . '(' -name bad -o -name worse ')' -prune -o \
      '(' -path '*/good/*' -o -path '*/better/*' ')' -name '*.txt' -type f -print
    

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

    set -o extendedglob # best in ~/.zshrc
    print -rC1 -- (^bad/)#*.txt~^*/good/*(ND.)
    
    print -rC1 -- (^(bad|worse)/)#*.txt~^*/(good|better)/*(ND.)
    

    或者对于数组中的列表:

    good=(good better best)
    bad=(bad worse worst)
    print -rC1 -- (^(${(~j[|])bad})/)#*.txt~^*/(${(~j[|])good})/*(ND.)
    

    不下降到称为,bad或(效率较低,如-path '*/good/*' ! -path '*/bad/*')的目录:

    print -rC1 -- **/*.txt~*/bad/*~^*/good/*(ND.)
    

    In zsh -o extendedglob,~是例外(和非)通配符运算符,而^是否定运算符,并且#是 0 或更多的前面的东西,如 regexp *。${(~j[|])array}将数组的元素与 连接起来|,将|其视为全局运算符而不是文字|与~.

    在zsh中,您可以在之后使用 PCRE 匹配set -o rematchpcre:

    set -o rematchpcre
    regex='^(?!.*/bad/).*/good/.*\.txt\Z'
    print -rC1 -- **/*(ND.e['[[ $REPLY =~ $regex ]]'])
    

    但是,对每个文件(包括bad目录中的文件)的 shell 代码的评估可能会比其他解决方案慢很多。

    还要注意 PCRE(与 zsh glob 相反)会阻塞在区域设置中不形成有效字符的字节序列,并且不支持 UTF-8 以外的多字节字符集。将区域设置固定为C喜欢find上述内容将解决此特定模式的问题。

    如果您[[ =~ ]]只想像 in 那样进行扩展正则表达式匹配bash,您也可以只加载 pcre 模块 ( zmodload zsh/pcre) 并使用[[ -pcre-match ]]而不是[[ =~ ]]进行 PCRE 匹配。

    或者您可以使用grep -zP(假设 GNUgrep或兼容)进行过滤:

    regex='^(?!.*/bad/).*/good/.*\.txt\Z'
    find . -type f -print0 |
      LC_ALL=C grep -zPe "$regex" |
      tr '\0' '\n'
    

    (尽管find仍然发现所有目录中的所有bad文件)。

    如果您需要对这些文件执行任何操作(每行打印一个除外),请替换tr '\0' '\n'为。xargs -r0 cmd


    ¹ 在任何情况下,我都不知道任何find支持类似 perl 或类似 vim 的正则表达式的实现,您需要环视运算符。

    • 8
  2. Inian
    2021-10-27T22:51:32+08:002021-10-27T22:51:32+08:00

    您不需要正则表达式,您可以使用-path谓词在任何级别排除具有特定名称的目录

    find . -type f -path '*/good/*' '!' -path '*/bad/*'
    
    • 6
  3. ti7
    2021-10-28T07:48:39+08:002021-10-28T07:48:39+08:00

    虽然它可能效率较低(尽管我不确定!)并且比find's 强大的过滤更“正确”(例如grep,这里的天真不适用于包含换行符的名称,尽管这些非常罕见并且通常表示错误) ,通常更容易堆叠几个实例,grep这些实例使用更简单的匹配和反向匹配依次过滤结果-v

    这需要对子字符串更加谨慎,以确保您确实找到了目录名称,但通常会提供更容易理解的语法,并且可以满足您的所有需求!

    find ./ | grep "/good/" | grep -v "/bad/" | grep '\.txt$'
    
    • 2

相关问题

  • 需要许多参数的实用程序的推荐界面是什么?[关闭]

  • 远程运行 X 应用程序,在远程主机上运行 GUI [关闭]

  • 使 mysql CLI 以交互方式向我询问密码

  • GNU find:在-exec中获取绝对和相对路径

  • 没有服务器的命令行 pub/sub?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve