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

有没有人知道如何通过数以千计的子目录search只包含1个文件,不超过1个文件的所有目录?

任何build议使用什么工具或简单的代码片段?

在PowerShell中,这是你可以做到的一个方法:

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

$_.PSIsContainer对dirs返回true,对文件返回false。 @()语法确保expression式的结果是一个数组。 如果它的长度是1,那么这个目录中只有一个文件。 这个例子还使用了一个嵌套pipe道,例如Get-ChildItem $_.Fullname | Where {...} Get-ChildItem $_.Fullname | Where {...}位于第一个脚本块内。

这是一个Perl解决scheme(在Windows上testing):

 #!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。
 C:\温度\ 1
 C:\ TEMP \ chrome_9999
 C:\ TEMP \ CR_3E.tmp

如果这是在Linux上,我会试图使用这样的命令。

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

find命令将打印出所有文件的目录名称。 然后我们通过sorting,然后使用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到一个以空字符结尾的string,然后可以将其作为xargs的参数。 您使用空终止的string,以便按预期方式处理空格。 在xargs中,{}字符将被每个传递的参数replace。

我想你可以用几行来制作一些东西

 File::Find 

像这样的东西。

 #!/usr/bin/perl use File::Find; my $base_dir = '/'; find( sub { # do stuff on each file here. $filename = $File::Find::name; $dir = $File::Find::dir; }, $base_dir ); ); 

编辑:我真的很喜欢Zoredache的查找方法更好,但你没有标记为Perl。

现在,如果你想对这些文件夹做些什么。

 $RootFolder = "c:\myfolder" $FoldersWithOnlyOneFile = Get-ChildItem $RootFolder -Recurse | ` Where {$_.PSIsContainer -and @( Get-ChildItem $_.Fullname | Where {!$_.PSIsContainer}).Length -eq 1 ` -and @( Get-ChildItem $_.Fullname | Where {$_.PSIsContainer}).Length -eq 0 } Foreach($folder in $FoldersWithOnlyOneFile) { $Folder.FullName Get-ChildItem $Folder.FullName }
$RootFolder = "c:\myfolder" $FoldersWithOnlyOneFile = Get-ChildItem $RootFolder -Recurse | ` Where {$_.PSIsContainer -and @( Get-ChildItem $_.Fullname | Where {!$_.PSIsContainer}).Length -eq 1 ` -and @( Get-ChildItem $_.Fullname | Where {$_.PSIsContainer}).Length -eq 0 } Foreach($folder in $FoldersWithOnlyOneFile) { $Folder.FullName Get-ChildItem $Folder.FullName } 

解决scheme:

 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框架的一部分)。

一个简单的解决scheme就是下降,每个文件的存在充电到包含它的目录:

 my %count = 0; ... sub wanted { return unless -f; $count{$File::Find::dir}++; } my @one_file_dirs = sort grep { $count{$_} == 1 } keys %count;