仅列出包含两个特定文件的子目录

仅列出包含两个特定文件的子目录

我正在使用 iPhone 的终端在 iOS 上运行以下代码,需要明确的是,该命令是使用名为 New Term 2 的精简终端调整在我的越狱 iPhone 中运行的:

cd /var/mobile/Library/Widgets
find . -maxdepth 3 -name 'index.html' -printf "%h\n"

这将返回包含 的文件夹列表index.html。我想知道如何添加另一个文件:(Config_extra.js如果存在,它将位于与 index.html 相同的文件夹中)以结果显示的方式添加到搜索中仅包含这两个文件的文件夹

提前致谢

答案1

你就快到了;一旦找到index.html文件,我们要求它通过(一些实现支持的非POSIX选项,包括iOS上的BSD )find在同一目录中查找Config_extra.js文件,成功后我们打印目录名称。-execdirfindfind

find . -maxdepth 3 -type f -name index.html -execdir test -f Config_extra.js \; -printf '%h\n'

上面的命令以展开的方式编写:

find . -maxdepth 3 \
  -type f -name index.html \
  -execdir test -f Config_extra.js \; \
  -printf '%h\n' ;

解决这个问题的另一种方法是perl使用长期以来File::Find作为标准和核心一部分的模块。Perl意思是,如果你有,perl你就有File::Find

cfg='Config_extra.js'
perl -MFile::Find -le '
  find(
    sub {
      my $cfg = $ARGV[0];
      my $d = $File::Find::dir;
      -d && "$d/" =~ m|(?:.*/){3}| && $File::Find::prune++;
      -f && /^index\.html$/ && -f $cfg && print($d);
    }, 
    shift,
  )
' . "$cfg"

答案2

您可以使用find -exec

find . -maxdepth 3 -name 'index.html' -exec sh -c '
  [ -f "${f%/*}/Config_extra.js" ]' find-sh {} \; -printf "%h\n"

如果您有一个很大的目录树,使用-exec ... +效果会更好:

find . -maxdepth 3 -name 'index.html' -exec sh -c '
  for f do
    d="${f%/*}"
    [ -f "$d/Config_extra.js" ] && printf "%s\n" "$d"
  done' find-sh {} +

或者,搜索目录:

find . -maxdepth 2 -type d -exec sh -c '
  [ -f "$1/index.html" ] && [ -f "$1/Config_extra.js" ]' find-sh {} \; -print

或使用-exec ... +

find . -maxdepth 2 -type d -exec sh -c '
  for d do
    [ -f "$d/index.html" ] && [ -f "$d/Config_extra.js" ] && printf "%s\n" "$d"
  done' find-sh {} +

答案3

如果 shell 是 zsh,你可以这样做:

print -rC1 - /var/mobile/Library/Widgets/*/*(N-/e['
  [[ -e $REPLY/index.html && -e $REPLY/Config_extra.js ]]']:t2)

打印包含这两个文件的目录的最后两个组成部分。

或者找到一个带有 glob 的文件,另一个带有eglob 限定符的文件,然后打印 2 分量尾巴这些文件的:

print -rC1 - /var/mobile/Library/Widgets/*/*/index.html(Ne['
  [[ -e $REPLY:h/Config_extra.js ]]']:h:t2)

答案4

find . -maxdepth 3 -name index.html -o -name Config_extra.js | 
  perl -lne '($dir,$base) = m:(^.*)/(.*$):;
             $dirs{$dir}++;
             END { foreach (sort keys %dirs) {print if $dirs{$_} == 2} }'

index.htmlfind 打印出匹配 或的文件的完整路径名Config_extra.js。这通过管道传输到一个 perl 脚本中,该脚本计算每个目录被看到的次数。处理完所有输入后,它会打印已经见过两次的目录。

这依赖于该find命令将绝不输出少于一次或多于两次的路径名。如果/当它匹配时一次index.html和/或如果/当它匹配时一次Config_extra.js

awk 中的算法大致相同:

find . -maxdepth 3 -name index.html -o -name Config_extra.js | 
  awk '{
         sub("/[^/]+$","",$0);
         dirs[$0]++
       }

       END {
         for (i in dirs) {
           if (dirs[i] == 2) print i
         }
       }'

相关内容