リネームスクリプト

優太の写真整理のために書いてみた。整理といえばナンバリング!! みたいな勢いで。

/*
	リネームスクリプト
*/

var zero_disit = 4;
var debug = false;

// Shell Application オブジェクトを通してフォルダ選択ダイアログを使う
var shapp_obj = new ActiveXObject("Shell.Application");
var target_folder_obj = shapp_obj.BrowseForFolder(0, "select the target folder", 0);

if(target_folder_obj == null){
	WScript.echo("process is canceled.");
	WScript.quit();
}

// Shell Application オブジェクトから Folder オブジェクトへの変換
// こうしないとパスが取れない
// …変なの
var temp_obj = target_folder_obj.Self;
var folder_path = temp_obj.Path;
target_folder_obj = null;

// さらに FileSystem オブジェクト経由で Folder オブジェクトを構築しないといけない!!
var fs_obj = new ActiveXObject("Scripting.FileSystemObject");
var folder_obj = fs_obj.GetFolder(temp_obj.Path);

// フォルダ内に含まれるファイルを全て取得
// 後々アクセスするために Enumerator オブジェクトでラップしないといけない!!
var files = new Enumerator(folder_obj.Files);
var numof_files = folder_obj.Files.Count;

// 処理を実行するか決定するためにダイアログを開く
//-1=自動で閉じない、4=はい&いいえ
var wsh_obj = WScript.CreateObject("WScript.Shell");
var ret = wsh_obj.Popup(folder_path + "\n" + numof_files + " files will be processing.", -1, "rename script", 4);
if(ret != 6) {
	WScript.echo("process is canceled.");
	WScript.quit();
}
	
// 本筋
var file_obj, ext, new_filename;
var count = 0;
for( ; ! files.atEnd() ; files.moveNext() ) {
	// Enumerator オブジェクト経由で File オブジェクトを取得
	file_obj = files.item();
	ext = fs_obj.GetExtensionName(file_obj.Name).toLowerCase();

	// db ファイルは処理対象外	
	if(ext == 'db') {
		continue;
	}

	new_filename = zero_padding(++count, zero_disit) + '.' + ext;

	if(debug == true) {
		WScript.echo(file_obj.Name + "\n" + ext + "\n" + new_filename);
	}

	// リネーム
	if(file_obj.Name != new_filename) {
		file_obj.Name = new_filename;
	}
}

WScript.echo("done.");
WScript.quit();

// ゼロ詰め関数
function zero_padding(number, disit) {
	// 数値 -> 文字列化
	var result = number + '';
	// 何文字かを取得・退避
	var number_length = result.length;

//	WScript.echo("number : " + number + "\nlength : " + number_length + "\ndisit : " + disit);

	// 最大桁数より大きい場合 false を返す
	if(number_length >= disit){
		return false;
	}

	// for で必要桁分 0 を付加する
	var numof_padding = disit - number_length;
	for(var i=0 ; i<numof_padding ; ++i){
		result = "0" + result;
	}

	return result;
}

上記で問題なく動作 (Windows XP SP2) 。まぁ 1000 枚以上の写真が処理対象だと動作がわからんのだけれども、桁数増やしてやれば対応できるように作ったし、問題はないだろうと。これでガンガン写真取れるぜ!!

ここから感想。WSH の調査しててもほとんどの人が VBScript で組むらしいのでサンプルソースがあまり参考にならなかった。ので、昔とった杵柄の Windows API うろ覚え知識を総動員して JScript の制御構文に当てはめていく形で書いてみた。

Windows API 叩きながらのプログラミングに関しては調査に時間かかる上にいらん知識ばかりが増えていく感じで「んー」。とりあえず同じ prototype 名なのに呼び出すコンテクストで違う挙動するオブジェクト群を何とかしようよ。いやまぁ、実際には違う prototype 名で性質の似たようなものを同じ名前で呼んでるんだろうけどさ。

// Shell Application オブジェクトから Folder オブジェクトへの変換
// こうしないとパスが取れない
// …変なの
var temp_obj = target_folder_obj.Self;
var folder_path = temp_obj.Path;
target_folder_obj = null;

それにしたって上記の処理の情報を得るのに 1 時間近く調べまわって出てきたページがひどかった。

フォルダを選択して [OK] をクリックすると、Shell の Folder オブジェクトのインスタンスが返されます。ただし、どういうわけか Shell の Folder オブジェクトには何も行うことができません。選択されたフォルダへのパスを取得する場合は、代わりに FolderItem オブジェクトを使用する必要があります (その理由は、まったくわかりません)。

http://www.microsoft.com/japan/technet/scriptcenter/resources/qanda/jun05/hey0617.mspx

さよか。