それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

php rmdir() で空じゃないフォルダを消すには?

php の rmdir には forece オプションがない。

普通に rmdir すると not empty directory って怒られるんですよね。

みんなどうやってんのかなーって調べたら system("rm -rf $target") してるみたい

せっかくなのでSPLで書いてみました。

<?php

function rm_f( $path ){

  $dir = new DirectoryIterator($path);
  if ( !$dir->isDir() ) { return false; }
  foreach($dir as $e ){
    if ( $e->isDot() ) continue;

    if ( $e->isDir() ) {
      rm_f($e->getPathName());
      rmdir($e->getPathName());
    }else{
      unlink ( $e->getPathName() ) ;
    }
  }
  return rmdir($path);

}

rm_f("/tmp/php-pdf-extractaUNYfA");

SPLが5.3あたりから標準仕様になっていて嬉しい。SPLはちょっと痒いところに手が届きそうで届かないもどかしい感じがすき。

ついでなのでglob で書いてみました

<?php

function rm_rf($path){
foreach( glob("$path/*") as $e ){
  if(is_directory($e)){ rm_rf($e);}
  else{unlink($e);}
}
rmdir($path);
}

ほかにも

  • FilesystemIterator
  • glob
  • opendir
  • readdir
  • array_walk_recursive

などなど再帰と配列が使えるものならなんでも出来そう。

ZIPとrm-rf の苦い記憶

通常はシェルでいいと思います。

<?php
shell_exec( "rm -rf $tmpname");

べつにシェルでもシェルでも。

<?php
$rm_command = "rm -rf \$TARGET"; //先にコマンド作っておいて
//exec
putenv("TARGET=". escapeshellarg($path));
shell_exec( $rm_command );
putenv("TARGET=");

でも、全部エスケープしろという無茶ルールに出会った苦い思い出がありまして。rm_rf はその時書きました。

べつにプログラム内部で作ってる文字列ならエスケープ不要よね?

tmpname で作った文字列までエスケープさせられてやり切れない苦い思い。

PHPってアレゲプログラマが多い世界なので、shell injection を生みかねない。」

このような前提にたってフールプルーフなんだろうけど。ソコまでやるかって感じはある。

コード作成者を馬鹿にしやがってという悔しさ。

チェックするならコミット側とテストでチェックすればいいじゃん。

シェル呼び出しで済む作業をプログラム書いてそのテストコード迄書く作業に、何の意味があるのだろうか

などと叫んだけど、ルールはルールだからで終ったとに、週明けには派遣先に私の席がなかった。うん。

良くわからないセキュリティ・ヤクザが監査に入って system 関数を全部エスケープしろだのツマラナイ単純置換やらされた辛い記憶がよみがえる。

「tmp に、自動生成画像まとめたzip ファイルの削除でエスケープは無いわと思った記憶。」

phpの案件は闇が深い。