批量重命名文件

时间:2022-08-28 11:33:41

      今天突然想给桌面换张壁纸,打开原来的壁纸文件夹,很多当时觉得不错的壁纸现在已经不能看了,删掉一些之后,壁纸文件的名称变得断断续续。当时下载时是按照数字顺序命名的,现在看上去多少有些别扭。于是突发奇想,能否批量给某一目录下的文件重命名,比如我现在的壁纸文件夹。

      首先我想到应该要打开一个目录,猜想是否有opendir之类的函数?果然有!在头文件<dirent.h>下面:

DIR* __cdecl __MINGW_NOTHROW opendir (const char*);

      

      返回值是DIR*,查看DIR的声明(opendir的上一个声明):

/*
* This is an internal data structure. Good programmers will not use it
* except as an argument to one of the functions below.
* dd_stat field is now int (was short in older versions).
*/
typedef struct
{
/* disk transfer area for this dir */
struct _finddata_tdd_dta;

/* dirent struct to return from dir (NOTE: this makes this thread
* safe as long as only one thread uses a particular DIR struct at
* a time) */
struct direntdd_dir;

/* _findnext handle */
intptr_tdd_handle;

/*
* Status of search:
* 0 = not started yet (next entry to read is first entry)
* -1 = off the end
* positive = 0 based index of next entry
*/
intdd_stat;

/* given path for dir with search pattern (struct is extended) */
chardd_name[1];
} DIR;

      

      看了注释狂汗。。。

      紧接着opendir函数的是readdir,这个又是我想要的,返回一个结构体指针:

struct dirent* __cdecl __MINGW_NOTHROW readdir (DIR*);

     

      这个结构体是DIR结构体的成员,再查看struct dirent的声明:

struct dirent
{
longd_ino;/* Always zero. */
unsigned shortd_reclen;/* Always zero. */
unsigned shortd_namlen;/* Length of name in d_name. */
chard_name[FILENAME_MAX]; /* File name. */
};

      

      很清晰,我想要的是d_name成员,这是目录下的文件名,只要用rename函数把文件名改掉即可,注意返回值小于0表示失败。

_CRTIMP int __cdecl __MINGW_NOTHROWrename (const char*, const char*);

 

      遍历所有文件后记得关闭文件closedir。

      完整的C代码:

#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>

#define DIRNAMECOUNT 100
#define COMMONCOUNT 90
#define EXTENSION 9

int main(int argc, char *argv[]) {
DIR *dirp;
struct dirent *dirt;
char dir_name[DIRNAMECOUNT];
char common_name[COMMONCOUNT] = "";
char extension[EXTENSION] = "";
int file_count = 1;

printf("Please input a common name: \n");
scanf("%s", common_name);
printf("Please input a extension: \n");
scanf("%s", extension);

if (argc != 2) {
printf("argument miss\n");
exit(1);
}

if ((dirp = opendir(argv[1])) == NULL) {
printf("open dir %s failed\n", argv[1]);
exit(1);
}

chdir(argv[1]);

while ((dirt = readdir(dirp)) != NULL) {
if (strcmp(dirt->d_name, "..") && strcmp(dirt->d_name, ".")) {
memset(dir_name, 0, sizeof(dir_name));
sprintf(dir_name, "%s_%d%s%s", common_name, file_count++, ".", extension);
if (rename(dirt->d_name, dir_name) < 0) {
printf("rename failed\n");
exit(1);
}
}
}

closedir(dirp);

return 0;
}

 

      这样只要输入文件名相同的部分(如wallpapers),以及扩展名(jpg),则文件可以按照序号重新命名。这样,所有的壁纸就都重命名了!

 

思考:

1.可以先读取文件的扩展名,保持更改时不变,否则文件无法查看(在windows系统下)。strtok函数可以分割字符串,以“.”分割获取最后一个字符串即扩展名。

2.对于要在原文件名的基础上增加新的字符,可以更改为sprintf(dir_name + strlen(dirt->d_name), ...)。

2.可以将自动获取当前目录的文件夹,getcwd函数可以做到。但是应该考虑到,可执行程序也会被重命名。可以在程序中过滤掉.exe文件,这取决于个人的把握。