auto_rec_rename.jsをいろいろ作り変える

ラベル: ,

前の関連記事:WSH JScriptでJavaScriptのお勉強(関数定義、クロージャ、this)


「20150328_203141_3600_004」(年月日_時分秒_区間秒_区間番号)を「区間開始日時-区間終了日時」へ変換するJScriptのauto_rec_rename.jsをいじって処理を追加します。まずはコードを見やすいように関数にできるところは関数にします。さらに同名ファイルができたときのエラー処理と書き込み中のファイルの改名を避ける処理を追加します。

繰り返し部分は関数にする

            //日付形式を数字羅列に変換
            start_n = start_dt.getFullYear() + ("0" + (start_dt.getMonth() + 1)).slice(-2) + ("0" + (start_dt.getDate())).slice(-2) + "_" + ("0" + (start_dt.getHours())).slice(-2) + ("0" + (start_dt.getMinutes())).slice(-2) + ("0" + (start_dt.getSeconds())).slice(-2);
            end_n = end_dt.getFullYear() + ("0" + (end_dt.getMonth() + 1)).slice(-2) + ("0" + (end_dt.getDate())).slice(-2) + "_" + ("0" + (end_dt.getHours())).slice(-2) + ("0" + (end_dt.getMinutes())).slice(-2) + ("0" + (end_dt.getSeconds())).slice(-2);
この2行はstart_dtとend_dtの部分が違うだけですのでこの部分を引数とする関数にしてしまいます。
var sh = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fldr = fso.GetFolder(sh.CurrentDirectory); //カレントディレクトリオブジェクトの取得。
var fc = new Enumerator(fldr.Files); //ファイルコレクションをEnumeratorオブジェクトにして取得。
var f, n, start_dt, int_sec, int_cnt, start_ms, start_n, end_n, new_name;
var end_dt = new Date();
var ext = "wav"; //改名対象拡張子。
//RegExpオブジェクトを作成。
var re = new RegExp("^(\\d{4})(\\d{2})(\\d{2})_(\\d{2})(\\d{2})(\\d{2})_(\\d+)_(\\d+)\\." + ext +"$");
//ファイルコレクションの各ファイルに対して。
for (; !fc.atEnd() ; fc.moveNext()) {
    f = fc.item(); //ファイルオブジェクトの取得。
    n = f.Name; //ファイル名の取得。
    //ファイル名の判別
    if (re.test(n)) {
        r = re.exec(n);//記録区間長と記録区間番号を抽出する正規表現の結果配列。
        //ファイル名から記録開始日時のDateオブジェクトを得る。1月を0として開始。
        start_dt = new Date(r[1], r[2] - 1, r[3], r[4], r[5], r[6]);
        int_sec = r[7] * 1000; //記録区間長(ミリ秒)
        int_cnt = r[8]; //記録区間番号
        start_ms = start_dt.getTime() + int_sec * (int_cnt - 1); //区間開始日時経過ミリ秒
        end_dt.setTime(start_ms + int_sec); //区間終了日時Dateオブジェクトを取得)
        start_dt.setTime(start_ms); //区間開始日時Dateオブジェクトを取得。
        //日付形式を数字羅列に変換
        start_n = date_num(start_dt);
        end_n = date_num(end_dt);
        new_name = start_n + "-" + end_n + "." + ext;//新しいファイル名の作成。
        //f.Name = new_name;//ファイル名を変更。
        WScript.Echo(n + "を" + new_name + "に改名");
    }
}
//日付形式を数字羅列に変換する関数
function date_num(dt) {
    return dt.getFullYear() + ("0" + (dt.getMonth() + 1)).slice(-2) + ("0" + (dt.getDate())).slice(-2) + "_" + ("0" + (dt.getHours())).slice(-2) + ("0" + (dt.getMinutes())).slice(-2) + ("0" + (dt.getSeconds())).slice(-2);
}
33行目で関数宣言で関数date_num()を作りました。
//日付形式を数字羅列に変換する関数
function date_num(dt) {
    return dt.getFullYear() + fm(dt.getMonth() + 1) + fm(dt.getDate()) + "_" + fm(dt.getHours()) + fm(dt.getMinutes()) + fm(dt.getSeconds());
    function fm(m) {
        return ("0" + m).slice(-2);
    }
}
数値を2ケタの固定長にしている部分も関数fm()にまとめました。

fm()も関数宣言での定義にしました。
var sh = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fldr = fso.GetFolder(sh.CurrentDirectory); //カレントディレクトリオブジェクトの取得。
var fc = new Enumerator(fldr.Files); //ファイルコレクションをEnumeratorオブジェクトにして取得。
var f, n, start_dt, int_sec, int_cnt, start_ms, start_n, end_n, new_name;
var ext = "wav"; //改名対象拡張子。
//RegExpオブジェクトを作成。
var re = new RegExp("^(\\d{4})(\\d{2})(\\d{2})_(\\d{2})(\\d{2})(\\d{2})_(\\d+)_(\\d+)\\." + ext +"$");
//ファイルコレクションの各ファイルに対して。
for (; !fc.atEnd() ; fc.moveNext()) {
    f = fc.item(); //ファイルオブジェクトの取得。
    n = f.Name; //ファイル名の取得。
    //ファイル名の判別
    if (re.test(n)) {
        r = re.exec(n);//記録区間長と記録区間番号を抽出する正規表現の結果配列。
        //ファイル名から記録開始日時のDateオブジェクトを得る。1月を0として開始。
        start_dt = new Date(r[1], r[2] - 1, r[3], r[4], r[5], r[6]);
        int_sec = r[7] * 1000; //記録区間長(ミリ秒)
        int_cnt = r[8]; //記録区間番号
        start_ms = start_dt.getTime() + int_sec * (int_cnt - 1); //区間開始日時経過ミリ秒
        //経過ミリ秒を数字羅列に変換
        end_n = date_num(start_ms + int_sec);//区間開始日時。
        start_n = date_num(start_ms);//区間終了日時。
        new_name = start_n + "-" + end_n + "." + ext;//新しいファイル名の作成。
        //f.Name = new_name;//ファイル名を変更。
        WScript.Echo(n + "を" + new_name + "に改名");
    }
}
//経過ミリ秒を年月日の数字羅列に変換する関数
function date_num(ms) {
    var dt = new Date();//Dateオブジェクトの生成。
    dt.setTime(ms);//経過ミリ秒からDateオブジェクトを取得。
    return dt.getFullYear() + fm(dt.getMonth() + 1) + fm(dt.getDate()) + "_" + fm(dt.getHours()) + fm(dt.getMinutes()) + fm(dt.getSeconds());
    //2桁に変換する関数。
    function fm(m) {
        return ("0" + m).slice(-2);
    }
}
経過ミリ秒からDateオブジェクトを取得する部分も引数が異なるだけなのでdate_num()関数に含めました。

記事を書き始めたときはこのdate_num()関数をコンストラクタ関数にして新しいオブジェクトを作る例を作ろうと思っていたのですが、この程度の処理ではコンストラクタ関数で新しいオブジェクトを作るメリットはなさそうなのでやめました

入力と出力が単一データの部分を関数にする


正規表現の結果配列を得てから新しいファイル名を得る部分は、正規表現配列の結果配列だけしかデータを使わず、ファイル名のみを得ているので、結果配列を引数として新しいファイル名を返す関数にしてしまいます。
var sh = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fldr = fso.GetFolder(sh.CurrentDirectory); //カレントディレクトリオブジェクトの取得。
var fc = new Enumerator(fldr.Files); //ファイルコレクションをEnumeratorオブジェクトにして取得。
var f, n, new_name;
var ext = "wav"; //改名対象拡張子。
//RegExpオブジェクトを作成。
var re = new RegExp("^(\\d{4})(\\d{2})(\\d{2})_(\\d{2})(\\d{2})(\\d{2})_(\\d+)_(\\d+)\\." + ext + "$");
//ファイルコレクションの各ファイルに対して。
for (; !fc.atEnd() ; fc.moveNext()) {
    f = fc.item(); //ファイルオブジェクトの取得。
    n = f.Name; //ファイル名の取得。
    //ファイル名の判別
    if (re.test(n)) {
        new_name = new_fname(re.exec(n));//正規表現配列から新しいファイル名を取得。
        //f.Name = new_name;//ファイル名を変更。
        WScript.Echo(n + "を" + new_name + "に改名");
    }
}
//正規表現配列から新しいファイル名を返す関数。
function new_fname(r) {
    //ファイル名から記録開始日時のDateオブジェクトを得る。1月を0として開始。
    var start_dt = new Date(r[1], r[2] - 1, r[3], r[4], r[5], r[6]);
    var int_sec = r[7] * 1000; //記録区間長(ミリ秒)
    var int_cnt = r[8]; //記録区間番号
    var start_ms = start_dt.getTime() + int_sec * (int_cnt - 1); //区間開始日時経過ミリ秒
    //経過ミリ秒を数字羅列に変換
    var end_n = date_num(start_ms + int_sec);//区間開始日時。
    var start_n = date_num(start_ms);//区間終了日時。
    return start_n + "-" + end_n + "." + ext;//新しいファイル名を返す。
}
//経過ミリ秒を年月日の数字羅列に変換する関数
function date_num(ms) {
    var dt = new Date();//Dateオブジェクトの生成。
    dt.setTime(ms);//経過ミリ秒からDateオブジェクトを取得。
    return dt.getFullYear() + fm(dt.getMonth() + 1) + fm(dt.getDate()) + "_" + fm(dt.getHours()) + fm(dt.getMinutes()) + fm(dt.getSeconds());
    function fm(m) {
        return ("0" + m).slice(-2);//固定長2桁を返す。
    }
}
関数new_fname()に括りだしました。

変数start_dt, int_sec, int_cnt, start_n, end_nは関数new_fname()でしか使われないのでローカル変数にできました。
//正規表現配列から新しいファイル名を返す関数。
function new_fname(r) {
    //ファイル名から記録開始日時のDateオブジェクトを得る。1月を0として開始。
    var start_dt = new Date(r[1], r[2] - 1, r[3], r[4], r[5], r[6]);
    var int_sec = r[7] * 1000; //記録区間長(ミリ秒)
    var int_cnt = r[8]; //記録区間番号
    var start_ms = start_dt.getTime() + int_sec * (int_cnt - 1); //区間開始日時経過ミリ秒
    //経過ミリ秒を数字羅列に変換
    var end_n = date_num(start_ms + int_sec);//区間開始日時。
    var start_n = date_num(start_ms);//区間終了日時。
    return start_n + "-" + end_n + "." + ext;//新しいファイル名を返す。
    //経過ミリ秒を年月日の数字羅列に変換する関数
    function date_num(ms) {
        var dt = new Date();//Dateオブジェクトの生成。
        dt.setTime(ms);//経過ミリ秒からDateオブジェクトを取得。
        return dt.getFullYear() + fm(dt.getMonth() + 1) + fm(dt.getDate()) + "_" + fm(dt.getHours()) + fm(dt.getMinutes()) + fm(dt.getSeconds());
        function fm(m) {
            return ("0" + m).slice(-2);//固定長2桁を返す。
        }
    }
}
関数date_num()は関数new_fname()からしか使わないのでnew_fname()のローカル関数にしてしまいました。

だいぶすっきりして流れが見やすくなりました。

ファイル名に秒を含めるか含めないか簡単に切れ替えられるようにする


改名後のファイル名を「年月日_時分秒-年月日_時分秒」という秒まで含んだものにすると長すぎてみにくいので「年月日_時分-年月日_時分」という秒を含まない形式にしようと思います。

しかし秒を含まない場合記録間隔によっては改名後に同名ファイルが出現する可能性があります。

同名のファイルが生じた場合は秒も含むファイル名にするように場合分けします。

まずはファイル名を「年月日_時分秒-年月日_時分秒」の形式か「年月日_時分-年月日_時分」の形式か簡単に出力を切り替えられるようにします。
var sh = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fldr = fso.GetFolder(sh.CurrentDirectory); //カレントディレクトリオブジェクトの取得。
var fc = new Enumerator(fldr.Files); //ファイルコレクションをEnumeratorオブジェクトにして取得。
var f, n, new_name;
var ext = "wav"; //改名対象拡張子。
//RegExpオブジェクトを作成。
var re = new RegExp("^(\\d{4})(\\d{2})(\\d{2})_(\\d{2})(\\d{2})(\\d{2})_(\\d+)_(\\d+)\\." + ext + "$");
//ファイルコレクションの各ファイルに対して。
for (; !fc.atEnd() ; fc.moveNext()) {
    f = fc.item(); //ファイルオブジェクトの取得。
    n = f.Name; //ファイル名の取得。
    //ファイル名の判別
    if (re.test(n)) {
        new_name = new_fname(re.exec(n));//正規表現結果配列からファイル名を取得。
        //f.Name = new_name;//ファイル名を変更。
        WScript.Echo(n + "を" + new_name[1] + "." + ext + "に改名");
    }
}
//正規表現結果配列から新しいファイル名を返す関数。戻り値は配列[年月日_時分-年月日_時分, 年月日_時分秒-年月日_時分秒]。
function new_fname(r) {
    //ファイル名から記録開始日時のDateオブジェクトを得る。1月を0として開始。
    var start_dt = new Date(r[1], r[2] - 1, r[3], r[4], r[5], r[6]);
    var int_sec = r[7] * 1000; //記録区間長(ミリ秒)
    var int_cnt = r[8]; //記録区間番号
    var start_ms = start_dt.getTime() + int_sec * (int_cnt - 1); //区間開始日時経過ミリ秒
    //経過ミリ秒を数字羅列に変換
    var end_n = date_num(start_ms + int_sec);//区間開始日時。
    var start_n = date_num(start_ms);//区間終了日時。
    var hhmm = start_n[0] + "-" + end_n[0];//新しいファイル名年月日_時分-年月日_時分。
    var hhmmss = start_n[0] + start_n[1] + "-" + end_n[0] + end_n[1];//新しいファイル名年月日_時分秒-年月日_時分秒。
    return [hhmm, hhmmss];
    //経過ミリ秒を年月日の数字羅列に変換する関数。戻り値は配列[年月日_時分, 秒]。
    function date_num(ms) {
        var dt = new Date();//Dateオブジェクトの生成。
        dt.setTime(ms);//経過ミリ秒からDateオブジェクトを取得。
        return [dt.getFullYear() + fm(dt.getMonth() + 1) + fm(dt.getDate()) + "_" + fm(dt.getHours()) + fm(dt.getMinutes()), fm(dt.getSeconds())];
        function fm(m) {
            return ("0" + m).slice(-2);//固定長2桁を返す。
        }
    }
}
秒を含む場合と含まない場合の2種類をどうやって出力するのかだいぶ悩みましたが、戻り値を配列にすることを思いつくと簡単に解決しました。

37行目で関数date_num()は秒の部分だけ別にした配列で値を返すようにします。

32行目で関数new_fname()が秒を含まない形式と秒を含む形式の2種類のファイル名を配列で返します。

15行目で戻り値の配列を受け取って、17行目で要素番号0を使って秒を含まない形式を出力しています。

20150328_203120_3600_001.wavを20150328_2031-20150328_2131.wavに改名
20150328_203141_3600_004.wavを20150328_2331-20150329_0031.wavに改名
続行するには何かキーを押してください . . .

秒を含む形式のファイル名にしたいときは要素番号1を使えばよいわけです。

スクリプトがあるフォルダの下層に改名前のデータフォルダ、その下層に改名後のデータフォルダにする


これまではスクリプトauto_rec_rename.jsと同じ階層にデータファイルを置いて処理していましたが、データファイルはデータフォルダに分けることにします。

C:.
│  auto_rec_rename.js
└─sox_data
    │  20150415_180552_300_027.mp3
    │  20150415_180552_300_045.mp3
    └─renamed
            20150415_2015-20150415_2020.mp3
            20150415_2020-20150415_2025.mp3
            20150415_2025-20150415_2030.mp3

このようにデータファイルはauto_rec_rename.jsの下層のsox_dataフォルダに置き、改名後のファイルはrenamedフォルダに入れることにします。

SoX(Sound eXchange)でMP3を扱うでSoXでMP3ファイルが扱えるようになったので今後はwavファイルではなくてmp3ファイルを対象に処理を行うことにします。
var sh = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fldr = fso.GetFolder(sh.CurrentDirectory); //カレントディレクトリオブジェクトの取得。
まずこの部分を変更します。

「カレントディレクトリ」の定義があいまいなようなので明確に「スクリプトがあるフォルダ」に変更します。(Windows Script Host でカレントフォルダを得る | NYORO PRESS

(ディレクトリはCUIでの用語、フォルダはGUIでの用語、というだけでディレクトリとフォルダは同じものを指す用語です。ディレクトリ - Wikipedia
var fso = new ActiveXObject("Scripting.FileSystemObject");
var s_path = String(WScript.ScriptFullName).replace(WScript.ScriptName, "");//このスクリプトがあるフォルダのパスを取得。
var fldr = fso.GetFolder(s_path + "sox_data"); //データフォルダオブジェクトの取得。
これでsox_dataフォルダにあるデータフォルダが処理対象になりました。
(実行したスクリプトのファイル名を含む完全なパスを取得する - ScriptFullName [WScript] [VBScript Tips]

改名後のファイルをrenamedフォルダに移動させる


f をファイルオブジェクトとすると f.Move(移動先のファイル名) で移動ができます。(ファイルの操作)

移動先のフォルダ名、ではなく、移動先のファイル名、が引数になっています。

単に移動させるときはファイル名まで指定しないといけないので面倒なのですが、改名を伴うときは移動と改名が同時にできるので都合がよいです。
var ext = "mp3"; //改名対象拡張子。
var data_dir = "sox_data";//データディレクトリ名。
var renamed_dir = "renamed";//改名後のデータをいれるディレクトリ名。
var fso = new ActiveXObject("Scripting.FileSystemObject");
var s_path = String(WScript.ScriptFullName).replace(WScript.ScriptName, "");//このスクリプトがあるフォルダのパスを取得。
var fldr = fso.GetFolder(s_path + data_dir); //データフォルダオブジェクトの取得。
var fc = new Enumerator(fldr.Files); //ファイルコレクションをEnumeratorオブジェクトにして取得。
var f, n, new_name;
//RegExpオブジェクトを作成。
var re = new RegExp("^(\\d{4})(\\d{2})(\\d{2})_(\\d{2})(\\d{2})(\\d{2})_(\\d+)_(\\d+)\\." + ext + "$");
renamed_dir = s_path + data_dir + "\\" + renamed_dir;//改名後のデータを入れるディレクトリのフルパス。
//ファイルコレクションの各ファイルに対して。
for (; !fc.atEnd() ; fc.moveNext()) {
    f = fc.item(); //ファイルオブジェクトの取得。
    n = f.Name; //ファイル名の取得。
    //ファイル名の判別
    if (re.test(n)) {
        new_name = new_fname(re.exec(n));//正規表現結果配列からファイル名を取得。
        f.Move(renamed_dir + "\\" + new_name[0] + "." + ext)
    }
}
//正規表現結果配列から新しいファイル名を返す関数。戻り値は配列[年月日_時分-年月日_時分, 年月日_時分秒-年月日_時分秒]。
function new_fname(r) {
略
} 
19行目でファイルの移動と改名を同時に行っています。

パス区切り文字は\でエスケープしないといけないようです。

Microsoft JScript 実行時エラー: 既に同名のファイルが存在しています。

同名ファイルがあるとエラーがでますので、try...catch - JavaScript | MDNで処理して、同名ファイルがあるときは秒までファイル名を含めることにします。
var ext = "mp3"; //改名対象拡張子。
var data_dir = "sox_data";//データディレクトリ名。
var renamed_dir = "renamed";//改名後のデータをいれるディレクトリ名。
var fso = new ActiveXObject("Scripting.FileSystemObject");
var s_path = String(WScript.ScriptFullName).replace(WScript.ScriptName, "");//このスクリプトがあるフォルダのパスを取得。
var fldr = fso.GetFolder(s_path + data_dir); //データフォルダオブジェクトの取得。
var fc = new Enumerator(fldr.Files); //ファイルコレクションをEnumeratorオブジェクトにして取得。
var f, n, new_name;
//RegExpオブジェクトを作成。
var re = new RegExp("^(\\d{4})(\\d{2})(\\d{2})_(\\d{2})(\\d{2})(\\d{2})_(\\d+)_(\\d+)\\." + ext + "$");
renamed_dir = s_path + data_dir + "\\" + renamed_dir;//改名後のデータを入れるディレクトリのフルパス。
//ファイルコレクションの各ファイルに対して。
for (; !fc.atEnd() ; fc.moveNext()) {
    f = fc.item(); //ファイルオブジェクトの取得。
    n = f.Name; //ファイル名の取得。
    //ファイル名の判別
    if (re.test(n)) {
        new_name = new_fname(re.exec(n));//正規表現結果配列からファイル名を取得。
        try {
            f.Move(renamed_dir + "\\" + new_name[0] + "." + ext)//「年月日_時分-年月日_時分」と改名して移動。
        } catch (e) {
            f.Move(renamed_dir + "\\" + new_name[1] + "." + ext)//「年月日_時分秒-年月日_時分秒」と改名して移動。
        }
    }
}
//正規表現結果配列から新しいファイル名を返す関数。戻り値は配列[年月日_時分-年月日_時分, 年月日_時分秒-年月日_時分秒]。
function new_fname(r) {
    //ファイル名から記録開始日時のDateオブジェクトを得る。1月を0として開始。
    var start_dt = new Date(r[1], r[2] - 1, r[3], r[4], r[5], r[6]);
    var int_sec = r[7] * 1000; //記録区間長(ミリ秒)
    var int_cnt = r[8]; //記録区間番号
    var start_ms = start_dt.getTime() + int_sec * (int_cnt - 1); //区間開始日時経過ミリ秒
    //経過ミリ秒を数字羅列に変換
    var end_n = date_num(start_ms + int_sec);//区間開始日時。
    var start_n = date_num(start_ms);//区間終了日時。
    var hhmm = start_n[0] + "-" + end_n[0];//新しいファイル名年月日_時分-年月日_時分。
    var hhmmss = start_n[0] + start_n[1] + "-" + end_n[0] + end_n[1];//新しいファイル名年月日_時分秒-年月日_時分秒。
    return [hhmm, hhmmss];
    //経過ミリ秒を年月日の数字羅列に変換する関数。戻り値は配列[年月日_時分, 秒]。
    function date_num(ms) {
        var dt = new Date();//Dateオブジェクトの生成。
        dt.setTime(ms);//経過ミリ秒からDateオブジェクトを取得。
        return [dt.getFullYear() + fm(dt.getMonth() + 1) + fm(dt.getDate()) + "_" + fm(dt.getHours()) + fm(dt.getMinutes()), fm(dt.getSeconds())];
        function fm(m) {
            return ("0" + m).slice(-2);//固定長2桁を返す。
        }
    }
}

最新のファイルは変更しないことにする


SoX(Sound eXchange)で音声感知録音:その2で録音して生成したファイルを処理するにあたって、録音中のファイルのファイル名は変更していけませんので最新のファイルは処理しないことにします。

ファイル名が年月日日と連番で構成されているので、最新のファイルかどうかはファイル名を昇順にならべて最終ファイルだけ処理からはずせば目的達成できます。

降順にして2番目の要素から開始にしてもよいですが、Enumerator オブジェクトは昇順でしか取り出せないようです。

最後のファイルかどうかは全部のファイルを確認しないとわかりませんので、処理対象のファイルオブジェクトをすべて一旦配列に収納します。(Array - JavaScript | MDN)
var ext = "mp3"; //改名対象拡張子。
var data_dir = "sox_data";//データディレクトリ名。
var renamed_dir = "renamed";//改名後のデータをいれるディレクトリ名。
var fso = new ActiveXObject("Scripting.FileSystemObject");
var s_path = String(WScript.ScriptFullName).replace(WScript.ScriptName, "");//このスクリプトがあるフォルダのパスを取得。
var fldr = fso.GetFolder(s_path + data_dir); //データフォルダオブジェクトの取得。
var fc = new Enumerator(fldr.Files); //ファイルコレクションをEnumeratorオブジェクトにして取得。
var f, new_name;
var f_arr = [];//処理対象ファイルオブジェクトを格納する配列。
//RegExpオブジェクトを作成。
var re = new RegExp("^(\\d{4})(\\d{2})(\\d{2})_(\\d{2})(\\d{2})(\\d{2})_(\\d+)_(\\d+)\\." + ext + "$");
renamed_dir = s_path + data_dir + "\\" + renamed_dir;//改名後のデータを入れるディレクトリのフルパス。
//ファイルコレクションの各ファイルに対して。
for (; !fc.atEnd() ; fc.moveNext()) {
    f = fc.item(); //ファイルオブジェクトの取得。
    //ファイル名の判別
    if (re.test(f.Name)) {
        f_arr.push(f);//処理対象となるファイルオブジェクトを配列に格納。ファイル名昇順に取得できているはず。
    } else {
        f.Delete();//処理対象とならないファイルは削除。
    }
}
for (var i = 0; i < f_arr.length - 1 ; i++) {
    f = f_arr[i];//配列からファイルオブジェクトを取得。最終要素は処理しない。
    new_name = new_fname(re.exec(f.Name));//正規表現結果配列からファイル名を取得。
    try {
        f.Move(renamed_dir + "\\" + new_name[0] + "." + ext);//「年月日_時分-年月日_時分」と改名して移動。
    } catch (e) {
        f.Move(renamed_dir + "\\" + new_name[1] + "." + ext);//「年月日_時分秒-年月日_時分秒」と改名して移動。
    } 
}
//正規表現結果配列から新しいファイル名を返す関数。戻り値は配列[年月日_時分-年月日_時分, 年月日_時分秒-年月日_時分秒]。
function new_fname(r) {
    //ファイル名から記録開始日時のDateオブジェクトを得る。1月を0として開始。
    var start_dt = new Date(r[1], r[2] - 1, r[3], r[4], r[5], r[6]);
    var int_sec = r[7] * 1000; //記録区間長(ミリ秒)
    var int_cnt = r[8]; //記録区間番号
    var start_ms = start_dt.getTime() + int_sec * (int_cnt - 1); //区間開始日時経過ミリ秒
    //経過ミリ秒を数字羅列に変換
    var end_n = date_num(start_ms + int_sec);//区間開始日時。
    var start_n = date_num(start_ms);//区間終了日時。
    var hhmm = start_n[0] + "-" + end_n[0];//新しいファイル名年月日_時分-年月日_時分。
    var hhmmss = start_n[0] + start_n[1] + "-" + end_n[0] + end_n[1];//新しいファイル名年月日_時分秒-年月日_時分秒。
    return [hhmm, hhmmss];
    //経過ミリ秒を年月日の数字羅列に変換する関数。戻り値は配列[年月日_時分, 秒]。
    function date_num(ms) {
        var dt = new Date();//Dateオブジェクトの生成。
        dt.setTime(ms);//経過ミリ秒からDateオブジェクトを取得。
        return [dt.getFullYear() + fm(dt.getMonth() + 1) + fm(dt.getDate()) + "_" + fm(dt.getHours()) + fm(dt.getMinutes()), fm(dt.getSeconds())];
        function fm(m) {
            return ("0" + m).slice(-2);//固定長2桁を返す。
        }
    }
}
これで必要な処理を追加できました。

WindowsのSoXではなぜか同名ファイルが生成されて(1)などがついたファイルができるので、それを20行目で削除しています。

これで出来上がりと思ったらrenamedフォルダがないときにエラーになることがわかりましたのでその処理も追加しました。
var ext = "mp3"; //改名対象拡張子。
var data_dir = "sox_data";//データディレクトリ名。
var renamed_dir = "renamed";//改名後のデータをいれるディレクトリ名。
var fso = new ActiveXObject("Scripting.FileSystemObject");
var s_path = String(WScript.ScriptFullName).replace(WScript.ScriptName, "");//このスクリプトがあるフォルダのパスを取得。
var fldr = fso.GetFolder(s_path + data_dir); //データフォルダオブジェクトの取得。
var fc = new Enumerator(fldr.Files); //ファイルコレクションをEnumeratorオブジェクトにして取得。
var f, new_name;
var f_arr = [];//処理対象ファイルオブジェクトを格納する配列。
//RegExpオブジェクトを作成。
var re = new RegExp("^(\\d{4})(\\d{2})(\\d{2})_(\\d{2})(\\d{2})(\\d{2})_(\\d+)_(\\d+)\\." + ext + "$");
renamed_dir = s_path + data_dir + "\\" + renamed_dir;//改名後のデータを入れるディレクトリのフルパス。
if (!fso.FolderExists(renamed_dir)){
    fso.CreateFolder(renamed_dir);//改名後のデータをいれるディレクトリがないときは作成する。
}
//ファイルコレクションの各ファイルに対して。
for (; !fc.atEnd() ; fc.moveNext()) {
    f = fc.item(); //ファイルオブジェクトの取得。
    //ファイル名の判別
    if (re.test(f.Name)) {
        f_arr.push(f);//処理対象となるファイルオブジェクトを配列に格納。ファイル名昇順に取得できているはず。
    } else {
        f.Delete();//処理対象とならないファイルは削除。
    }
}
for (var i = 0; i < f_arr.length - 1 ; i++) {
    f = f_arr[i];//配列からファイルオブジェクトを取得。最終要素は処理しない。
    new_name = new_fname(re.exec(f.Name));//正規表現結果配列からファイル名を取得。
    try {
        f.Move(renamed_dir + "\\" + new_name[0] + "." + ext);//「年月日_時分-年月日_時分」と改名して移動。
    } catch (e) {
        f.Move(renamed_dir + "\\" + new_name[1] + "." + ext);//「年月日_時分秒-年月日_時分秒」と改名して移動。
    } 
}
//正規表現結果配列から新しいファイル名を返す関数。戻り値は配列[年月日_時分-年月日_時分, 年月日_時分秒-年月日_時分秒]。
function new_fname(r) {
    //ファイル名から記録開始日時のDateオブジェクトを得る。1月を0として開始。
    var start_dt = new Date(r[1], r[2] - 1, r[3], r[4], r[5], r[6]);
    var int_sec = r[7] * 1000; //記録区間長(ミリ秒)
    var int_cnt = r[8]; //記録区間番号
    var start_ms = start_dt.getTime() + int_sec * (int_cnt - 1); //区間開始日時経過ミリ秒
    //経過ミリ秒を数字羅列に変換
    var end_n = date_num(start_ms + int_sec);//区間開始日時。
    var start_n = date_num(start_ms);//区間終了日時。
    var hhmm = start_n[0] + "-" + end_n[0];//新しいファイル名年月日_時分-年月日_時分。
    var hhmmss = start_n[0] + start_n[1] + "-" + end_n[0] + end_n[1];//新しいファイル名年月日_時分秒-年月日_時分秒。
    return [hhmm, hhmmss];
    //経過ミリ秒を年月日の数字羅列に変換する関数。戻り値は配列[年月日_時分, 秒]。
    function date_num(ms) {
        var dt = new Date();//Dateオブジェクトの生成。
        dt.setTime(ms);//経過ミリ秒からDateオブジェクトを取得。
        return [dt.getFullYear() + fm(dt.getMonth() + 1) + fm(dt.getDate()) + "_" + fm(dt.getHours()) + fm(dt.getMinutes()), fm(dt.getSeconds())];
        function fm(m) {
            return ("0" + m).slice(-2);//固定長2桁を返す。
        }
    }
}

参考にしたサイト


Windows Script Host でカレントフォルダを得る | NYORO PRESS
CurrentDirectory プロパティの結果は一定しないようです。

ディレクトリ - Wikipedia
CUIではディレクトリ、GUIではフォルダというようです。

実行したスクリプトのファイル名を含む完全なパスを取得する - ScriptFullName [WScript] [VBScript Tips]
JScriptの例が豊富にあります。

ファイルの操作
WSHでのファイル操作の方法。

JavaScript リファレンス - JavaScript | MDN
MDN(Mozilla Developer Network)によるJavaScriptリファレンス。

ドライブとフォルダの操作
WSHのフォルダ操作の方法。

次の関連記事:Visual Studio Community 2013でWSH JScriptファイルを作成してデバッグする方法

PR

0 件のコメント:

コメントを投稿