C++批量修改文件系统
前情提要:从bilibili下了鸟的歌,不晓得发生甚么事了,居然下载了两遍。
哇我好蓝瘦啊,难道我要一个个改吗,有200多个诶!
我寻思可以用C++做一个面向过程的程序啊
于是在此感谢C++调用文件函数的教程:
原文链接:https://blog.csdn.net/u012500825/article/details/41947013
成品介绍:
1.可以读取文件路径下所有文件的文件名,以字符串的形式输出(getFiles函数)
2.可以匹配含有特定字符的文件,*鸟.mp3
3.可以对被匹配的文件进行重命名操作
原理与修改意见:本质就是递归,如果是文件夹就下一层,否则就遍历所有的文件
在else里面就是直接对某个文件fileinfo进行操作,如果要改造的话就在这里删改
do
{ //如果是目录,迭代之
if((fileinfo.attrib & _A_SUBDIR))
{
if(strcmp(fileinfo.name,".") != 0 && strcmp(fileinfo.name,"..") != 0)
getFiles( p.assign(path).append("\\").append(fileinfo.name), files );
//p.assign(path).append("\\").append(fileinfo.name)
//意思是 给p赋值path 附加\ 再附加当前文件的名字
}
else
{
rename(p.assign(path).append("\\").append(fileinfo.name).c_str(), new_name.c_str());//真实修改
}
}while(_findnext(hFile, &fileinfo) == 0);//文件夹里的文件未被完全遍历
改造成品:可以直接使用exe
#include <io.h>
#include <iostream>
#include <vector>
#include <string>
#include <string.h>
#include <sstream>
using namespace std;
/*
两个特殊变量time_t(long int), _fsize_t(unsigned)
和常量宏_MAX_FNAME表文件名的最大长度
包括下面这个结构体都在头文件被定义
struct _finddata_t
{
unsigned attrib;//表示文件的属性
//_A_ARCH(存档)、_A_HIDDEN(隐藏)、_A_NORMAL(正常)、_A_RDONLY(只读)、_A_SUBDIR(文件夹)、_A_SYSTEM(系统)。
//这些都是在<io.h>中定义的宏,可以直接使用,而本身的意义其实是一个无符号整型(只不过这个整型应该是2的几次幂,从而保证只有一位为1,而其他位为0)。
//既然是位表示,那么当一个文件有多个属性时,它往往是通过位或的方式,来得到几个属性的综合。例如只读+隐藏+系统属性,应该为:_A_HIDDEN | _A_RDONLY | _A_SYSTEM 。
time_t time_create;/存储文件创建时间
time_t time_access;//文件最后一次被访问的时间。
time_t time_write;//文件最后一次被修改的时间。
_fsize_t size;//文件的大小,即字节数
char name[_MAX_FNAME];
};*/
void getFiles(string path, vector<string>& files )
{
//文件句柄
long hFile = 0;
//文件信息
struct _finddata_t fileinfo;
string p;
/*
long _findfirst( char *filespec, struct _finddata_t *fileinfo );
如果查找成功的话,将返回一个long型的唯一的查找用的句柄(一个唯一编号)
这个句柄将在_findnext函数中被使用。若失败,则返回-1。
*/
if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) != -1)
{
do
{ //如果是目录,迭代之
if((fileinfo.attrib & _A_SUBDIR))
{
if(strcmp(fileinfo.name,".") != 0 && strcmp(fileinfo.name,"..") != 0)
getFiles( p.assign(path).append("\\").append(fileinfo.name), files );
//p.assign(path).append("\\").append(fileinfo.name)
//意思是 给p赋值path 附加\ 再附加当前文件的名字
}
else
{//如果不是,加入列表
files.push_back(p.assign(path).append("\\").append(fileinfo.name) );
}
}while(_findnext(hFile, &fileinfo) == 0);//文件夹里的文件未被完全遍历
_findclose(hFile);
}
}
string C,behind;
int next[110];
bool check(string tex){
int n=tex.size(),m=C.size(),l=behind.size()-1;
for(int i=n-1;l>=0;i--){//判断后缀名
if(behind[l]!=tex[i]) return false;
l--;
}//一个纯粹的KMP匹配
int i=-1,j=-1,ans=0;
while(i<n-1)
{
while(j>-1 && tex[i+1]!=C[j+1]) j=next[j];
if(tex[i+1]==C[j+1])
{
j++;
if(j==m-1) { ans++; j=next[j]; }
}i++;
}return ans>0;
}
string replace;
void reNameFiles(string path,int flag)//本函数的代码含义请看上面getFiles函数
{
long hFile = 0;
struct _finddata_t fileinfo;
static int i=1;
string p,s;
if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) != -1){
do{
if((fileinfo.attrib & _A_SUBDIR)){
if(strcmp(fileinfo.name,".") != 0 && strcmp(fileinfo.name,"..") != 0)
reNameFiles( p.assign(path).append("\\").append(fileinfo.name),flag);
}
else{
s=fileinfo.name;
if(check(s)){//筛选
stringstream ss;ss<<i;i++;
string new_name = p.assign(path).append("\\")+replace+string(ss.str()+behind);//全部附上SB方便删除
if(flag==1) cout<<s<<endl;//输出原文件名
if(flag==2) cout<<new_name<<endl;//输出改后文件名
if(flag==3) rename(p.assign(path).append("\\").append(fileinfo.name).c_str(), new_name.c_str());//真实修改
}
}
}
while(_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}
int main()
{
cout<<"请输入路径:"<<endl;
char filePath[10010];
//char filePath*= "E:\\(置顶)信息学\\(置顶) 安装包 && 杂项\\bilibili";
//或输入E:\(置顶)信息学\(置顶) 安装包 && 杂项\bilibili
cin.getline(filePath,1000);
/*vector<string> files;
getFiles(filePath, files);
int size = files.size();
for (int i = 0;i < size;i++) cout<<files[i].c_str()<<endl;
cout<<"已获取该路径下的所有文件"<<endl;*/
//==============================================================================
cout<<"\n请输入文件后缀:示例:.mp3" <<endl;
cin>>behind;
cout<<"\n请输入筛选条件(字符串匹配):示例:(1)" <<endl;
cin>>C;int m=C.size();next[0]=-1;//KMP预处理
for(int i=0,j=-1;i<m-1;i++)
{
while(j>-1 && C[i+1]!=C[j+1]) j=next[j];
if(C[i+1]==C[j+1]) j++;
next[i+1]=j;//要么是0,要么继承后缀
}
cout<<"请确认您即将更改的文件:"<<endl;
reNameFiles(filePath,1);
//==============================================================================
cout<<"\n请输入改名标示字符串:示例:SB" <<endl;
cout<<"它们即将被改为:"<<endl;
cin>>replace;
reNameFiles(filePath,2);
//==============================================================================
cout<<"\n确认更改(y/n):"<<endl;
char p;cin>>p;
if(p=='y') reNameFiles(filePath,3);
return 0;
}
成品效果如下:
背景故事的后续:
有空我用Qt做一个 [doge]