抱歉标题不好,但这是我能做的最好的! :d
我有一个脚本,每次调用指定的函数时都会创建一个新项目。
每个项目必须存储在自己的文件夹中,并带有项目名称。但是,如果您没有指定名称,脚本只会将其命名为“new projectX”,其中X是一个渐进数字。
随着时间的推移,用户可以重命名文件夹或删除一些文件夹,因此每次脚本运行时,它都会检查可用的最小编号(未被其他文件夹使用)并创建相关文件夹。
现在我设法制作了一个我觉得可以正常工作的程序,但是我想听听你是否可以,或者由于我对该语言缺乏经验而无法发现错误。
while ( defined( $file = readdir $projects_dir ) )
{
# check for files whose name start with "new project"
if ( $file =~ m/^new project/i )
{
push( @files, $file );
}
}
# remove letters from filenames, only the number is left
foreach $file ( @files )
{
$file =~ s/[a-z]//ig;
}
@files = sort { $a <=> $b } @files;
# find the smallest number available
my $smallest_number = 0;
foreach $file ( @files )
{
if ( $smallest_number != $file )
{
last;
}
$smallest_number += 1;
}
print "Smallest number is $smallest_number";
答案 0 :(得分:3)
以下是此类问题的基本方法:
sub next_available_dir {
my $n = 1;
my $d;
$n ++ while -e ($d = "new project$n");
return $d;
}
my $project_dir = next_available_dir();
mkdir $project_dir;
如果您愿意使用与Perl string auto-increment feature完美匹配的命名模式,则可以进一步简化代码,从而无需$n
。例如,newproject000
。
答案 1 :(得分:1)
我想我会使用类似的东西:
use strict;
use warnings;
sub new_project_dir
{
my($base) = @_;
opendir(my $dh, $base) || die "Failed to open directory $base for reading";
my $file;
my @numbers;
while ($file = readdir $dh)
{
$numbers[$1] = 1 if ($file =~ m/^new project(\d+)$/)
}
closedir($dh) || die "Failed to close directory $base";
my $i;
my $max = $#numbers;
for ($i = 0; $i < $max; $i++)
{
next if (defined $numbers[$i]);
# Directory did not exist when we scanned the directory
# But maybe it was created since then!
my $dir = "new project$i";
next unless mkdir "$base/$dir";
return $dir;
}
# All numbers from 0..$max were in use...so try adding new numbers...
while ($i < $max + 100)
{
my $dir = "new project$i";
$i++;
next unless mkdir "$base/$dir";
return $dir;
}
# Still failed - give in...
die "Something is amiss - all directories 0..$i in use?";
}
测试代码:
my $basedir = "base";
mkdir $basedir unless -d $basedir;
for (my $j = 0; $j < 10; $j++)
{
my $dir = new_project_dir($basedir);
print "Create: $dir\n";
if ($j % 3 == 2)
{
my $k = int($j / 2);
my $o = "new project$k";
rmdir "$basedir/$o";
print "Remove: $o\n";
}
}
答案 2 :(得分:0)
本身没有任何错误,但这是实现单个目标的大量代码(获取目录的最小索引。
核心模块,几个子模型和少数Schwartzian变换将使代码更加灵活:
use strict;
use warnings;
use List::Util 'min';
sub num { $_[0] =~ s|\D+||g } # 'new project4' -> '4', 'new1_project4' -> '14' (!)
sub min_index {
my ( $dir, $filter ) = @_;
$filter = qr/./ unless defined $filter; # match all if no filter specified
opendir my $dirHandle, $dir or die $!;
my $lowest_index = min # get the smallest ...
map { num($_) } # ... numerical value ...
grep { -d } # ... from all directories ...
grep { /$filter/ } # ... that match the filter ...
readdir $dirHandle; # ... from the directory contents
$lowest_index++ while grep { $lowest_index == num( $_ ) } readdir $dirhandle;
return $lowest_index;
}
# Ready to use!
my $index = min_index ( 'some/dir' , qr/^new project/ );
my $new_project_name = "new project $index";
答案 3 :(得分:0)
试试这个:
#!/usr/bin/env perl
use strict;
use warnings;
# get the current list of files
# see `perldoc -f glob` for details.
my @files = glob( 'some/dir/new\\ project*' );
# set to first name, in case there are none others
my $next_file = 'new project1';
# check for others
if( @files ){
# a Schwartian transform
@files = map { $_->[0] } # get original
sort { $a->[1] <=> $b->[1] } # sort by second field which are numbers
map { [ $_, do{ ( my $n = $_ ) =~ s/\D//g; $n } ] } # create an anonymous array with original value and the second field nothing but digits
@files;
# last file name is the biggest
$next_file = $files[-1];
# add one to it
$next_file =~ s/(.*)(\d+)$/$1.($2+1)/e;
}
print "next file: $next_file\n";