ディレクトリ内を再帰的に検索して何かファイル処理をする

この手のことは、たま〜に必要になる。
で、都度BATか何かを書いて対応していたのだが
すぐ忘れるので、毎回調べるハメになる。
さすがにアホらしいのでメモしとく。

何で書こうか…

一度挫折しているWSH(vbsじゃなくてjsね)でやってみよ。

んで、できたのがこれ

最近Cしか書いてないからちょっと戸惑った。

var _fs = WScript.CreateObject("Scripting.FileSystemObject");
var _current = _fs.GetFolder(".");

// HACK: ハッシュテーブルで持てば簡単に検索できた気がしたが…
var _ext = ['.hws', '.Hbp', '.tws', '.hsf', '.hwp', '.tps'];
var _delExt = ['.orig'];

// HACK: 起動時の引数で開始ディレクトリを決める
ScanFolder(_current);


/**
 * 再帰的に特定拡張子のファイルを処理する
 * @author foohogehoge
 * @param folder 処理を開始するディレクトリ
 */
function ScanFolder(folder)
{
        var subfc = new Enumerator(folder.SubFolders);
        for(; !subfc.atEnd(); subfc.moveNext()){
            // サブフォルダを持っていれば再起処理
            ScanFolder(subfc.item());
        }

        var fc = new Enumerator(folder.Files);
        for(; !fc.atEnd(); fc.moveNext()){
            var fileName = fc.item().Name;
            var extIndex = fileName.lastIndexOf(".");
            var extName = fileName.substring(extIndex, fileName.length);

            //=================================================
            // 以下各ファイル処理。もう少しきれいにならんものか。。

            // 読み取り専用属性を解除
            for(var i=0;i<_ext.length;i++){
                if(_ext[i] == extName){
                    fc.item().Attributes &= 0xFE;
                    /**
                     * MEMO: Attributesについて
                     *   0 標準ファイル 
                     *   1 読み取り専用ファイル 
                     *   2 隠しファイル 
                     *   4 システムファイル 
                     *   8 ディスクドライブボリュームラベル(*) 
                     *  16 フォルダ(*) 
                     *  32 アーカイブ属性 
                     *  64 リンクまたはショートカット(*) 
                     * 128 圧縮ファイル(*) 
                     *  (*)は値の取得のみが可能
                     */
                    break;
                }
            }
            
            // 不要ファイルを削除
            for(var i=0;i<_delExt.length;i++){
                if(_delExt[i] == extName){
                    WScript.Echo("削除:" + fileName);
                    //_fs.DeleteFile(fc.item());  // 読み取り専用だと削除しない
                    fc.item().Delete(true);       // 読み取り専用でも強制削除
                    break;
                }
                else if(fileName.substring(0,2) == ".#"){
                    WScript.Echo("削除:" + fileName);
                    //_fs.DeleteFile(fc.item());  // 読み取り専用だと削除しない
                    fc.item().Delete(true);       // 読み取り専用でも強制削除
                    break;
                }
            }
            //=================================================
        }
}

参考

jsは情報が少なくて困る。MSのサンプルもvbsメインだし。
下記ページの作者の方に感謝します。

Windows Scripting Host
JavaScript の配列と連想配列の違い - IT戦記


http://www.jfast.net/~saikawa/wsh/file.html#attrib
※このページの情報はちょっと違ってました。(Attribute関連) 加減算で属性変更はまずいですね。