有没有人知道如何通过数以千计的子目录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;