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 / 问题 / 524035
Accepted
Harper - Reinstate Monica
Harper - Reinstate Monica
Asked: 2019-06-11 07:26:42 +0800 CST2019-06-11 07:26:42 +0800 CST 2019-06-11 07:26:42 +0800 CST

Unix 是否被多个 prunes 和 type f 淹没了?

  • 772

我在这个魔方上花了几天时间。我为解决一个问题所做的任何事情都会破坏另一个问题。

我在兼容 POSIX 的 MacOS X 10.5 到 10.14 上。我在 Perl 脚本的上下文中调用它

  system ("find blah blah > FILENAME");

我需要 Unix 'find' 同时做所有这些事情。

  • 从卷根开始,例如/Volumes/My HD
  • 不要跨文件系统
  • 仅打印文件,而不是目录或符号链接
  • 甚至不要进入多个目录,例如net dev system. (即不探索/Volumes/foo/dev/,但探索/Volumes/foo/Users/Jim/ dev /github/twonky/)
  • 起点可能包含空格

现在我正在做以下事情:(为了便于阅读,分成几行;实际上是一长行)

 Find -x '/Volumes/foo/' 
    -path '/Volumes/foo//dev/*' -prune
    -path '/Volumes/foo//net/*' -prune
    -path '/Volumes/foo//system/*' -prune
    -o -type f -print

双 / 的原因是find的打印输出包含 // 因为起点以 / 结尾。修剪路径必须一致,否则它们将不匹配。为什么起点以/结尾?因为如果没有,则find在名称中带有空格的任何起点上都会失败,例如“我的高清”。试过了。

现在, find 仅排除列表中的第一个目录。其余的,它只是忽略。我目前正在 OS X 10.5 上进行测试,但我需要在任何地方都可以使用的东西。

多个修剪 + 仅文件 + 文件名中的空格是否太过分了?我只是要求太多find吗?

find
  • 3 3 个回答
  • 116 Views

3 个回答

  • Voted
  1. L. Scott Johnson
    2019-06-11T08:17:42+08:002019-06-11T08:17:42+08:00

    您需要一个“或”来完成第二次匹配——没有一条路径可以同时匹配-path '/Volumes/foo//dev/*'和-path '/Volumes/foo//net/*'

    Find -x '/Volumes/foo/' 
        \( -path '/Volumes/foo//dev/*' 
        -o -path '/Volumes/foo//net/*' 
        -o -path '/Volumes/foo//system/*' \) -prune
    -o -type f -print
    
    • 5
  2. Best Answer
    Patrick Mevzek
    2019-07-12T11:47:02+08:002019-07-12T11:47:02+08:00

    我的回答是纯 Perl 解决方案。

    使用此沙箱:

    $ tree -F Volumes/ 
    Volumes/ 
    └── My\ HD/
        ├── Users/
        │   └── Jim/
        │       └── dev/
        │           └── github/
        │               └── twonky/
        │                   └── i_there.txt
        ├── dev/
        ├── net/
        ├── start.bat
        └── system/
            └── hello
    
    9 directories, 3 files
    

    以下 Perl 代码使用File::Find:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use feature 'say';
    
    use File::Find;
    
    my $start = 'Volumes/My HD';
    my $start_dev = (stat($start))[0];
    my @exclude = qw/net dev system/;
    my %skipdir;
    
    sub wanted {
        my $name = $_;
        return if (stat($name))[0] != $start_dev;
        $skipdir{$File::Find::name} = 1 if $File::Find::dir eq $start && grep { $name eq $_ } @exclude;
        if (exists($skipdir{$File::Find::dir})) {
            $skipdir{$File::Find::name} = 1 if -d $name;
            return;
        }
        return if ! -f $name;
        say "Got: $File::Find::name";
    
    }
    
    my %args = (
        wanted => \&wanted,
        follow => 1,
        follow_skip => 1,
    );
    
    
    find(\%args, $start);
    

    给出预期(如果我理解正确的话):

    Got: Volumes/My HD/start.bat
    Got: Volumes/My HD/Users/Jim/dev/github/twonky/i_there.txt
    

    它是一个 POC,它可以被增强。

    另请注意,您拥有find2perl记录在案的工具,该工具能够使用相同的标准将特定find调用转换为关联的 Perl 代码。File::Find

    现在Path::Class代码可能看起来更简单/更容易阅读(对于相同的结果):

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use feature 'say';
    
    use Path::Class;
    
    my $start = Path::Class::Dir->new('Volumes/My HD');
    my @exclude = qw/net dev system/;
    
    $start->recurse(callback => sub {
        my $node = shift;
        if ($node->is_dir) {
            return $node->PRUNE if $node->parent eq $start && grep { $node->dir_list(-1) eq $_ } @exclude;
            return;
        }
        return $node->PRUNE if $node->stat()->dev != $start->stat()->dev;
        say 'Got: ', $node->stringify();
    }, preorder => 1)
    
    • 2
  3. Harper - Reinstate Monica
    2019-07-22T16:31:14+08:002019-07-22T16:31:14+08:00

    在您的帮助下,我得以稳定“查找”。然而,将代码从 OS X 10.5 移动到 10.10再次破坏了它。最后的机会。'find' 实在是太迟钝了,文档不足且不一致,而且它是一个 unix 核心功能,看在 Pete 的份上!这个。这就是为什么我讨厌别人的代码。我开始埋头学习 File::Find,然后想“我在做什么?我可以在 20 分钟内自己编写代码”。

    我总结了一下。

    sub iterate {
      my ($mydir, $ref_FH, $homevol, $ref_excludes) = @_;  # last is ref to hash
    
      return if (defined ($ref_excludes -> {$mydir}));   # No excludes
    
      my $thisvol = (stat($mydir))[0];    # What's my volume?
      return if ($thisvol != $homevol) ;  # No crossing volumes
    
      opendir (my $DIR, $mydir);
      while (defined (my $file = readdir($DIR))) {
        next if ($file eq '.' or $file eq '..');
        my $full = "$mydir/$file";   
    
        if (-l $full) {                                   # symlink
                                                             # nope
        } elsif (-f $full) {                              # file
          print {$$ref_FH} "$full\n";                        # print it
        } elsif (-d $full) {                              # dir
          &iterate($full, $ref_FH, $homevol, $ref_excludes); # iterate
        }
      }
    }
    

    而且速度很快。而且很轻——这段代码的大小是格式化“find”的arg列表的代码的一半(并且更易于维护)!

    • 1

相关问题

  • 如果未引用 -name 后面的模式,则 find 的奇怪行为

  • 将变量从子shell打印到父shell [重复]

  • 检查某个文件夹是否存在于某个目录中

  • 从命令行查找和替换 CSS 文件中的颜色

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

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