概要

フォルダー内に含まれるファイル名のうちフォルダ名に全角英数があった場合、半角に変換するプログラムです。サブフォルダー内のフォルダ名も変換対象になります。
コマンドラインで動作します。
使用方法
rendir_zen2han [フォルダー名]

ソースコード

UNICODEに対応し、32bit/64bit対応です。

rendir_ze2han.cpp

// ディレクトリ(フォルダー)の中のフォルダーを検索(サブディレクトリの中も含めて)しフォルダー名の英数字を半角に変換する
// 2014/04/06
// Visual C++ 2008 コマンドライン用
// 使用方法
//   rendir_zen2han [フォルダー名]

#include <windows.h>
#include <stdio.h>
#include <locale.h>
#include <tchar.h>
#include "list.hpp"

struct FILE_LINK{
	TCHAR* full_name;			//	ファイル名
	TCHAR* sname;
	FILE_LINK* next;	//	次のファイル名へのポインタ
	FILE_LINK(){
		full_name=0;
		next=0;
	}
};

struct FILE_LIST : public LIST{
	void append(FILE_LINK* p){
		LIST::append((void*)p);
	}
	FILE_LINK* next(void){
		return (FILE_LINK*)LIST::next();
	}
	FILE_LINK* first(void){
		return (FILE_LINK*)LIST::first();
	}
};

//	再帰呼び出しによりサブディレクトリ内の指定ファイルを検索する

int get_dir_list(FILE_LIST* list,TCHAR* pass){
	WIN32_FIND_DATA FindFileData;
	HANDLE hFind;
	TCHAR find_pass[MAX_PATH];
	TCHAR sub_pass[MAX_PATH];
	int num=0;	//	見つかったファイル数

	int len=(int)_tcslen(pass)+1;
	_stprintf_s(find_pass,sizeof(find_pass)/sizeof(TCHAR),_TEXT("%s\\*.*"),pass);	//	サブディレクトリの検索
	hFind = FindFirstFile(find_pass, &FindFileData);
	if(hFind != INVALID_HANDLE_VALUE){
		do{
			if( (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
				if(_tcscmp(FindFileData.cFileName,_TEXT("..")) && _tcscmp(FindFileData.cFileName,_TEXT("."))){	//	親ディレクトリは無視する
					_stprintf_s(sub_pass,sizeof(sub_pass)/sizeof(TCHAR),_TEXT("%s\\%s"),pass,FindFileData.cFileName);
					int num2=get_dir_list(list,sub_pass);	//	サブディレクトリの中を検索
					if(num2==0){
						FILE_LINK* l=new FILE_LINK;
						l->full_name=_tcsdup(sub_pass);
						l->next=0;
						l->sname=l->full_name+len;
						list->append(l);
					}
					num+=num2;
					++num;
				}
		}while( FindNextFile(hFind,&FindFileData) );
	}
	FindClose(hFind);
	return num;
}		


//	全角文字を半角に変換する 変換された文字があった場合はtrueを返す

bool zen2han(TCHAR* s){
	bool f=false;
	TCHAR* p=s;

	while(*p){
		TCHAR* ep=_TEXT("¥/:*?<>|{}%()&”~");	//	フォルダーに使用できない文字
		while(*ep){
			if(*ep==*p)
				break;
			++ep;
		}
		if(*ep==_T('\0')){
			if(0xff01<=*p  && *p<=0xff5d){	//	全角数字英字記号の場合
				*p-=0xff00-0x20;
				f=true;
			}else if(*p==_T(' ')){
				*p=_T(' ');
				f=true;
			}
		}
		++p;
	}
	return f;
}



int _tmain(int argc, TCHAR** argv){
	_tsetlocale(LC_ALL,_TEXT(""));

	FILE_LIST file_list;
	int num;
	TCHAR src[1024];

	if(argc!=2){
		_tprintf(_TEXT("使用方法\n\trendir_zen2han [フォルダー名]\n"));
		return 1;
	}

	num=get_dir_list(&file_list,argv[1]);
	int n=0;
	FILE_LINK* p=file_list.first();
	while(p){
		_tcscpy_s(src,sizeof(src)/sizeof(TCHAR),p->full_name);
		if(zen2han(p->sname)==true){
			++n;
			MoveFile(src,p->full_name);
			_tprintf(_TEXT("%s %s\n"),src,p->full_name);
		}
		p=file_list.next();
	}
	_tprintf(_TEXT("%i個のフォルダーを変更しました。\n"),n);
	return 0;
}

list.hpp

#ifndef LIST_HPP
#define LIST_HPP 1

class LINK{
	LINK* next;
	LINK* back;
	void* data;
protected:
	LINK(){
		next=0;
		back=0;
		data=0;
	}
	void set(void* d){
		data=d;
	}
	friend class LIST;
	friend int cmp(const void* d,const void* s){
		if((char*)d>(char*)s)
			return 1;
		if((char*)d<(char*)s)
			return -1;
		return 0;
		
	}
};

typedef void* LPVOID;

class LIST{
	LINK* top;	//	リストの先頭
	LINK* end;	//	リストの最後尾
	LINK* pos;	//	リストのカレントポジション
	int max;	//	リストの要素数
protected:
	LIST(){
		pos=top=end=0;
		max=0;
	}
	void append(void* d){	//	リストの最後尾にデータを追加
		LINK* p=new LINK;
		++max;
		p->data=d;
		if(top==0){
			pos=top=end=p;
		}else{
			end->next=p;
			p->back=end;
			end=p;
		}
	}
	void* next(void){	//	カレントポジジョンからデータを得た後、カレントポジションを1個進める。
		LINK* t=pos;
		if(pos==0){
			return 0;
		}else{
			pos=pos->next;
			return t->data;
		}
	}
	void* first(void){	//	カレントポジションを先頭に移動させ先頭データを得た後、カレントポジションを1個進める。
		pos=top;
		return next();
	}
	void all_del(void){	//	リスト全部を削除する
		while(top){
			LINK* t=top->next;
			delete top;
			top=t;
		}
		top=end=pos=0;
		max=0;
	}
	void repeat_del(int(*cmp )(const void* d,const void* s)){	//	ソートされたリストから重複する要素を削除
		LINK* lp=top;
		if(lp){
			LINK* bp=0;
			while(lp){
				if(bp){
					if( (*cmp)((void**)&lp->data,(void**)&bp->data) ){	//	前の要素と異なる場合
						bp=lp;
					}else{	//	前の要素と同じ場合
						LINK* t=lp->next;
						del(lp);
						--max;
						lp=t;
						continue;
					}
				}else
					bp=lp;
				lp=lp->next;
			}
		}
	}	
	void qsort(int(*cmp )(const void* d,const void* s)){
		if(max){
			int n=0;
			LPVOID* vec=new LPVOID[max];	//	リストの要素を配列にコピーする
			if(vec==0)
				return;
			void* p;
			p=first();
			while(p){
				vec[n++]=p;
				p=next();
			}
			::qsort((void*)vec,max,sizeof(LPVOID),cmp);
			LINK* lp=top;						//	配列をリストにコピー
			n=0;
			while(lp){
				lp->set(vec[n++]);
				lp=lp->next;
			}
			delete vec;
		}
	}
	void del(LINK*	p){	// リストからpを削除する
		if(p){
			if(p==top){
				LINK* t=top;
				top=top->next;
				top->back=0;
				if(pos==p){
					pos=p->next;
				}
				delete p;
				return;
			}
			if(p==end){
				LINK* t=end;
				end=end->back;
				end->next=0;
				delete p;
				return;
			}
			LINK* t=p;
			p->back->next=p->next;
			p->next->back=p->back;
			if(pos==p){
				pos=p->next;
			}
			delete t;
		}

	}
public:
	int get_max(void){
		return max;
	}
};

#endif

ソース・実行ファイル

Visual C++ 2008用 ソース・実行ファイルのダウンロード