如何查找仅包含一个文件的目录?

如何查找仅包含一个文件的目录?

有谁知道如何在数千个子目录中搜索所有仅包含 1 个文件且不超过 1 个文件的目录?

关于使用什么工具或简单的代码片段有什么建议吗?

答案1

在 PowerShell 中,你可以这样做:

PS> Get-ChildItem -recurse | `
     Where {$_.PSIsContainer -and `
           @(Get-ChildItem $_.Fullname | Where {!$_.PSIsContainer}).Length -eq 1}

$_.PSIsContainer对于目录,返回 true;对于文件,返回 false。该语法@()确保表达式的结果是一个数组。如果其长度为 1,则该目录中只有一个文件。此示例还使用了嵌套管道,例如Get-ChildItem $_.Fullname | Where {...}在第一个 Where 脚本块中。

答案2

如果这是在 Linux 上,我会倾向于使用这样的命令。

find . -type 'f' -printf '%h\n' | sort | uniq -c

find 命令将打印出所有文件的目录名称。然后我们对其进行排序,然后使用 uniq 的 -c 选项来获得每个目录的文件数量。一旦您知道每个目录的数量,就应该很容易 grep 出值为 1 的目录。

如果您希望对目录执行操作并将其保持在一行中,则可以通过 awk 将结果传送到 xargs。例如,要删除每个文件夹:

find . -type 'f' -printf '%h\n' | sort | uniq -c | awk '{ if ($1 == "1") printf "%s%c",$2,0 }' | xargs -0 -I {} rm -rf {}

这会将每个值为 1 的目录打印到以空字符结尾的字符串中,然后可以将其作为 xargs 的参数。使用以空字符结尾的字符串,这样空格就会按预期处理。在 xargs 中,{} 字符将被每个传递的参数替换。

答案3

这是一个 Perl 解决方案(在 Windows 上测试):

#!perl

use strict;
use warnings;

use File::Find;
use File::Slurp;
use File::Spec::Functions qw(catfile canonpath rel2abs);

my ($top) = @ARGV;
die "Provide top directory\n" unless defined($top) and length $top;

find(\&wanted, $top);

sub wanted {
    my $name = $File::Find::name;
    return unless -d $name;
    return unless 1 == grep { -f catfile($name, $_) } read_dir $name;
    print canonpath(rel2abs $name), "\n";
}

输出:

C:\Temp> f 。
目录:\Temp\1
目录:\Temp\chrome_9999
目录:\Temp\CR_3E.tmp

答案4

解决方案:

sub wanted {
    my $name = $File::Find::name;
    return unless -d $name;
    return unless 1 == grep { -f catfile($name, $_) } read_dir $name;
    print canonpath(rel2abs $name), "\n";
}

不必要地读取每个目录来计算其中的项目,然后在实际下降时再次读取它(作为框架的一部分File::Find)。

一个更简单的解决方案就是下降,将每个文件的存在记录到包含它的目录中:

my %count = 0;
...
sub wanted {
  return unless -f;
  $count{$File::Find::dir}++;
}

my @one_file_dirs = sort grep { $count{$_} == 1 } keys %count;

相关内容