フォルダー内のファイル名の全角英数を半角に変換するプログラム

icon 項目のみ表示/展開表示の切り替え

概要

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

ソースコード

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

rename_ze2han.cpp

// ディレクトリ(フォルダー)の中の指定されたファイル名を検索してファイル名の全角英数を半角英数に変換する(サブディレクトリの中も含めて)
// Visual C++ 2008 Unicode 32/64bitコマンドライン用
// 2014/04/06
// 使い方
//   rename_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(){
                sname=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,TCHAR* card){
        WIN32_FIND_DATA FindFileData;
        HANDLE hFind;
        TCHAR find_pass[MAX_PATH];
        TCHAR find_top_pass[MAX_PATH];
        TCHAR sub_pass[MAX_PATH];
        TCHAR make_pass[MAX_PATH];
        int num=0;      //      見つかったファイル数
        int l=_tcslen(pass);
        int c=pass[l-1];        //      パスの最後の文字
        _tcscpy_s(find_top_pass,sizeof(find_top_pass)/sizeof(TCHAR),pass);
        if(c!=_T('\\') && c!=_T(':')){
                find_top_pass[l]=_T('\\');
                find_top_pass[l+1]=_T('\0');
        }

        _stprintf_s(find_pass,sizeof(find_pass)/sizeof(TCHAR),_TEXT("%s*.*"),find_top_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"),find_top_pass,FindFileData.cFileName);                                
                                        num+=get_dir_list(list,sub_pass,card);  //      サブディレクトリの中を検索
                                }
                }while( FindNextFile(hFind,&FindFileData) );
        }
        FindClose(hFind);
        int pass_len=(int)_tcslen(find_top_pass)+1;
        _stprintf_s(find_pass,sizeof(find_pass)/sizeof(TCHAR),_TEXT("%s%s"),find_top_pass,card);        //      ファイルの検索
        hFind = FindFirstFile(find_pass, &FindFileData);
        if(hFind != INVALID_HANDLE_VALUE){
                do {
                        if( !(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){
                                ++num;
                                _stprintf_s(make_pass,sizeof(make_pass)/sizeof(TCHAR),_TEXT("%s%s"),find_top_pass,FindFileData.cFileName);
                                size_t len=_tcslen(make_pass);
                                TCHAR* n=new TCHAR[len+1];
                                _tcscpy_s(n,len+1,make_pass);
                                FILE_LINK* p=new FILE_LINK;
                                p->full_name=n;
                                p->sname=n+pass_len;
                                p->next=0;
                                list.append(p);
                        }
                }while( FindNextFile(hFind,&FindFileData) );
                return num;
        }else
                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* pass;
        TCHAR files[32];
        TCHAR* file_p[16];
        int i=0;
        TCHAR src[1024];

        switch(argc){
        case 2:
                pass=argv[1];
                _tcscpy_s(files,sizeof(files)/sizeof(TCHAR),_TEXT("*.*"));
                break;
        case 3:
                pass=argv[1];
                _tcscpy_s(files,sizeof(files)/sizeof(TCHAR),argv[2]);
                break;
        default:
                _tprintf(_TEXT("rename_zen2han [ディレクトリ名] [ワイルカード]\n"));
                _tprintf(_TEXT("[ワイルカード]省略時は*.*が適用される\n"));
                _tprintf(_TEXT("ワイルカードは*.jpg;*.bmpの様に;で区切ることにより複数指定可能\n"));
                return 1;
        }

        TCHAR* pp=files;
        TCHAR* top=files;
        while(*pp){
                if(*pp==_T(';')){
                        *pp=_T('\0');
                        file_p[i++]=top;
                        top=pp+1;
                }
                ++pp;
        }
        if(*top){
                file_p[i++]=top;
        }
        file_p[i]=0;
        i=0;
        while(file_p[i]){
                num=get_dir_list(file_list,pass,file_p[i]);
                ++i;
        }
        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用 ソース・実行ファイルのダウンロード