首页 > 代码库 > 批量重命名文件

批量重命名文件

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

      首先我想到应该要打开一个目录,猜想是否有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_t	dd_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 dirent		dd_dir;

	/* _findnext handle */
	intptr_t		dd_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
	 */
	int			dd_stat;

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

      

      看了注释狂汗。。。

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

struct dirent* __cdecl __MINGW_NOTHROW readdir (DIR*);

     

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

struct dirent
{
	long		d_ino;		/* Always zero. */
	unsigned short	d_reclen;	/* Always zero. */
	unsigned short	d_namlen;	/* Length of name in d_name. */
	char		d_name[FILENAME_MAX]; /* File name. */
};

      

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

_CRTIMP int __cdecl __MINGW_NOTHROW	rename (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文件,这取决于个人的把握。

批量重命名文件