ぬるぽを見かけたら 全力でぶっ叩くのみ


by Denullpo Smasher Hammerson
カレンダー
S M T W T F S
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

正規表現でファイル名一括変更ツール

DOS由来の貧弱renコマンドでは面倒な作業でてきたので、PHPで適当に書いてみた。
正規表現でぶっつけ本番やらかすと大抵失敗するので、テスト機能も入ってます。

とりあえず
% php pregren.php -g *.txt
な感じでリネーム対象ファイル群の列挙テスト
これはglobパターンで書く

次は
% php pregren.php -t *.txt "/^(prefix)(\d+)(suffix)(\.txt)$/"
な感じでリネーム対象部分のマッチングテスト
これはpregパターンで書く
マッチングに成功するとマッチングパターン、失敗したら [*skip*] が出てくる。
-s オプションを付けると、[*skip*]だけを検出できます。

次は
% php pregren.php -T *.txt "/^(prefix)(\d+)(suffix)(\.txt)$/" $2$4
な感じでリネームテスト

テスト結果に問題なければ、
% php pregren.php *.txt "/^(prefix)(\d+)(suffix)(\.txt)$/" $2$4
な感じでテストオプションだけ外してexecute.


なお、自動実行の際は事前にサニタイズしとくヨロシ
さもないと、インジェクションのエ♠ジ♠キ♥




pregren.php:
<?php
// preg renamer: version 1.0
// (C)2010 Denullpo Smash Hammerson
$opt_t1=false;
$opt_t2=false;
$opt_g=false;
$opt_s=false;
$opt_d=false;
$eoo=false;
$files=null;

// get options & glob pattern
@array_shift($argv);
while(count($argv)>0){
$a=@array_shift($argv);
if($eoo){
$files=$a;
break;
}
if($a=='--')$eoo=true;
elseif($a[0]=='-'||$a[0]=='/'){
switch($a){
case '-d': case '/d': $opt_d=true; break;
case '-g': case '/g': $opt_g=true; break;
case '-s': case '/s': $opt_s=true; break;
case '-t': case '/t': $opt_t1=true; break;
case '-T': case '/T': $opt_t2=true; break;
default:
fwrite(STDERR,"error: Invalid option ($a.)\n");
exit(-1);
}
}
else{
$files=$a;
break;
}
}

// needing extra args
if($opt_g)$need=0;
elseif($opt_t1)$need=1;
else $need=2;

if(count($argv)<$need){
echo "usage:\n";
echo "pregren.php [-d] [-g] [-t] [-T] [-s] [--] files pattern replace\n";
echo "-g glob test\n";
echo "-t pattern test\n";
echo "-T replace test\n";
echo "-s skip test\n";
echo "-d include directory name\n";
echo "-- end of options\n";
exit(-1);
}

// glob pattern to files
$files=glob($files);
if(!is_array($files)){
fwrite(STDERR,"error: Invalid file pattern.\n");
exit(-1);
}
if(count($files)<1){
fwrite(STDERR,"error: File not found.\n");
exit(-1);
}

// get preg pattens
if(!$opt_g){
$ptn=$argv[0];
if(!$opt_t1){
$rep=$argv[1];
}
}

// will do
if($opt_g)echo "glob test:\n";
elseif($opt_t1)echo "test: $ptn\n";
elseif($opt_t2)echo "test: $ptn => $rep\n";
else echo "rename: $ptn => $rep\n";

foreach($files as $n){
// not -d option: skip directory
if(is_dir($n) && !$opt_d)continue;
// -g option: glob test
if($opt_g){
echo "$n\n";
continue;
}
// -t option: preg test
if($opt_t1){
$f=preg_match($ptn,$n,$a);
if(is_null($a)){
fwrite(STDERR,"error: Syntax error.\n");
exit(-1);
}
if($f){
$n2=implode(' ',$a);
if(!$opt_s)echo "$n: $n2\n";
}
else{
echo "$n [*skip*]\n";
}
continue;
}

// skip unmatched file
if(!preg_match($ptn,$n,$a)){
if($opt_t2)echo "$n [*skip*]\n";
continue;
}

// replacing
$n2=preg_replace($ptn,$rep,$n);
if(is_null($n2)){
fwrite(STDERR,"error: Syntax error.\n");
exit(-1);
}
if(!$opt_s)echo "$n => $n2\n";

// not -T option: do rename
if(!$opt_t2){
rename($n,$n2);
}
}

?>

[PR]
by denullpo | 2010-10-10 11:32 | こっち関係