ファイルを作成日時の古い順に任意の値から連番にしたいと思いました。

昔取った写真とかが統一性のない名前のために整理したいんですよね。

batファイルは嫌いなのでc言語でやってみます。


で、作るのに意外と結構時間がかかりました。

それはわざわざリストを実装したのと、winapiとかの使い方を調べていたからです。


リストは構造体に次の構造体のアドレスを示す値を入れておいて、動的に構造体のメモリを確保していく感じです。

最初は自分なりに考えて実装しようと思っていたのですが、リストの最初のアドレスをどう管理するのかが思いつかなくてグローバル変数で管理しようとか考えていました。

でもそれは嫌だなとか思ってリストに前の構造体のアドレスを含めるようにして、どこからでも最初と最後を辿れるようにしたりしました。

けれど結局はネットで少し調べてみて、リストを使う関数内でそのポインタを宣言して、そのポインタに最初のアドレスを確保しておく感じになりました。

kuinとかでリストは少し使ってはいたのですが、アップデートで昔のコードとかが使えなくなってkuinをもう使っていなかったのですっかりリストがどんな感じか忘れていました。

リストのソートは作成日時で整理しようとして、ソート方法はめんどかったのでただのバブルソートです。

まあとりあえず、リストの勉強になりました。


あとはwinapiですが、ファイルのリネームをどうやるか調べたところ、c言語にはrename関数があるのでそれを使おうと思っていました。

けれどなんかうまくいかなかったので、winapiでMoveFileでやろうとしたのですが、やっぱりコピーした方が安全かなと思いCopyFileに落ち着きました。

もっとc言語を勉強しないといけないです。


注意事項としては、もともと持っているファイルを自分でコピーするとファイルの作成時刻が変わってしまうことがあることです。

例えばもともと

0.jpg

1.jpg

2.jpg

~

10.jpg

11.jpg

こんな感じファイルがあったとして、自分でフォルダごとコピーすると

0.jpg

1.jpg

10.jpg

11.jpg

~

みたいになることがあります。

そのためその状態で以下に示すコードを実行すると、

最初の数を3と設定したら

3.jpg (←0.jpg)

4.jpg (←1.jpg)

5.jpg (←10.jpg)

6.jpg (←11.jpg)

~

こんな感じになることがあるので、少し確認が必要です。

そういうこともあったのでリネームや移動ではなくファイルのコピーとしました。


#include <windows.h>
#include <stdio.h>
#include<stdlib.h>
typedef struct {
	DWORD time;
	char name[100];
	struct list *next;
}list;

list *getListEnd(list *p)
{
	while(p->next!=NULL){
		p=p->next;
	}
	return p;
}

int getListNum(list *L)
{
	int num=0;
	while(L->next!=NULL){
		num++;
		L=L->next;
	}
	return num;
}

list *addList(list *L,DWORD t,char *name)
{
	list *newL=(list*)calloc(1,sizeof(list));
	newL->time=t;
	strcpy(newL->name,name);
	if(L==NULL)return newL;	
	//前のリストのnextに追加
	list *p=getListEnd(L);
	p->next=newL;
	return L;
}
//not used
list *getListPrev(list *L,list *a)
{
	while((int64_t)L->next!=(int64_t)a){
		L=L->next;
		if(L->next==NULL)return NULL;
	}
	return L;
}

void swapList(list *L,list *a,list *b)
{
	list p;
	strcpy(p.name,a->name);
	p.time=a->time;
	strcpy(a->name,b->name);
	a->time=b->time;
	strcpy(b->name,p.name);
	b->time=p.time;
}

void sort(list *L)
{
	int listSize=getListNum(L);
	for(int i=listSize;i>0;i--){
		list *p=L;
		list *q=p->next;
		for(int j=i;j>0;j--){
			if(p->time>q->time){
				swapList(L,p,q);
			}
			p=p->next;
			q=p->next;
		}
	}
}

void main(int argc, char *argv[])
{   
	puts("Number the files in order of creation date.");
	puts("Enter the path and first value of the folder containing the files you want to sequentially number.");
	puts("example:C:\\aaa\\ 5");
	char path[200];
	int firstN;
	scanf("%s %d",path,&firstN);

	WIN32_FIND_DATA fd;
    HANDLE hFind;
	FILETIME fileTime;
	strcat(path,"*");
    hFind = FindFirstFile(path, &fd);
    list *fileL=NULL;
    do {
    	//ファイルのみ
    	if((fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)==0){
    		fileTime=fd.ftCreationTime;
    		fileL=addList(fileL,fileTime.dwLowDateTime,fd.cFileName);
    	}
    } while (FindNextFile(hFind, &fd));
    FindClose(hFind);
    
	sort(fileL);
	
	//名前書き換え
	list *p=fileL;
	int n=firstN;
	path[strlen(path)-1]=0;
	char path2[100];
	sprintf(path2,"%ssorted\\",path);
	puts(path2);
	CreateDirectory(path2, NULL);
	while(1){
		char fname[100],renban[100];
		sprintf(fname,"%s%s",path,p->name);
		sprintf(renban,"%ssorted\\%d.jpg",path,n);
		puts(fname);
		puts(renban);
		CopyFile(fname,renban,TRUE);
		if(p->next==NULL)break;
		p=p->next;
		n++;
	}
    getchar();
}