rm xxx
mv xxx ~/.Trash
rm命令简单但伤害性极大,现在用C++自己写一个rm命令执行mv * /Users/xxx/.Transh(废纸篓),给自己一碗回头药。
1、源码:
#include <iostream>
#include <regex>
#include <string>
#include <ctime>
using namespace std;
#define BUF_SIZE 1024
#define flag regex_constants::ECMAScript
bool exec(const char* cmd,bool blog){
int retcode(system(cmd));
if(retcode==0) return true;
else{
// cout<<cmd<<" return errcode: "<<retcode<<endl;
return false;
}
if(false){
/*
FILE * p_file = NULL;
p_file = popen(cmd, "r");
if (!p_file) {
fprintf(stderr, "sh error, check rm source code! ! !");
return false;
}
regex reg("No such file or directory",flag);
char buf[BUF_SIZE];
bool bReturn(false);
char* res=fgets(buf, BUF_SIZE, p_file);
// mac上不论popen()执行成功与否,此处调用fgets()会引发“[1] 21015 segmentation fault”错误
cout<<res<<endl;
while (res != NULL) {
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/popen.html
bReturn=true;
if(blog)
cout<<buf<<endl;
if(regex_search(buf,reg)){
return false;
}
res=fgets(buf, BUF_SIZE, p_file);
}
if(! bReturn) return false;
pclose(p_file);
return true;
*/
}
};
int main(int argc,char* argv[]){
if(argc<=1){
cout<<"please input a valid file!"<<endl;
return 1;
}
int iCountSuc(-1),iCountFail(-1);
string cmdsls[argc-1],cmdsmv[argc-1],errs[argc-1];
char mv[BUF_SIZE],desti[BUF_SIZE],fail[BUF_SIZE];
strcpy(mv,"mv ");
strcpy(desti," /Users/haypin/.Trash");
strcpy(fail," FAILED! ! !");
char chard[3],charf[3],chari[3],charP[3];
char charR[3],charr[3],charv[3],charW[3];
strcpy(chard,"-d");
strcpy(charf,"-f");
strcpy(chari,"-i");
strcpy(charP,"-P");
strcpy(charR,"-R");
strcpy(charr,"-r");
strcpy(charv,"-v");
strcpy(charW,"-W");
regex regd(chard,flag); // 去除,mv直接移动目录
regex regf(charf,flag); // 保留,与mv -f作用相同
regex regi(chari,flag); // 保留,与mv -i作用相似
regex regP(charP,flag); // 去除
regex regR(charR,flag); // 去除,mv直接移动目录
regex regr(charr,flag); // 去除,等价于-R
regex regv(charv,flag); // 保留,与mv -v作用相同
regex regW(charW,flag); // break,Attempt to undelete the named files
regex reghyphen("--",flag);
bool bhyphen(false);
string mv_joint;
mv_joint.append("mv ");
for(int i(1);i<argc;i++){
bhyphen=regex_search(argv[i],reghyphen);
if(!bhyphen){ // --前的都是选项,--后的不是选项
bool bd(regex_search(argv[i],regd));
bool bP(regex_search(argv[i],regP));
bool bR(regex_search(argv[i],regR));
bool br(regex_search(argv[i],regr));
bool bW(regex_search(argv[i],regW));
if(bd || bP || bR || br) {
cout<<"continue "<<argv[i]<<endl;
continue;
}
if(bW) {
cout<<"-W mean Attempt to undelete the named files, will break"<<endl;
break;
}
bool bf(regex_search(argv[i],regf));
bool bi(regex_search(argv[i],regi));
bool bv(regex_search(argv[i],regv));
if(bf) {
mv_joint.append(charf);
mv_joint.append(" ");
continue;
}
if(bi) {
mv_joint.append(chari);
mv_joint.append(" ");
continue;
}
if(bv) {
mv_joint.append(charv);
mv_joint.append(" ");
continue;
}
}
cmdsls[i-1].append("ls "); // ls /Users/haypin/.Trash/argv[i],如果存在就mv argv[i] desti/argv[i]+08-10-14:23:11
cmdsls[i-1].append(desti);
cmdsls[i-1].append("/");
cmdsls[i-1].append(argv[i]);
cmdsmv[i-1].append(mv_joint);
cmdsmv[i-1].append(argv[i]);
cmdsmv[i-1].append(desti);
if(exec(cmdsls[i-1].c_str(),false)){
time_t now(time(0));
tm *now_tm(localtime(&now));
char buf[100];
strcpy(buf,"/");
cmdsmv[i-1].append(buf);
cmdsmv[i-1].append(argv[i]);
strcpy(buf,"\\ \\ ");
cmdsmv[i-1].append(buf);
sprintf(buf,"%d",now_tm->tm_mon);
cmdsmv[i-1].append(buf);
cmdsmv[i-1].append("-");
sprintf(buf,"%d",now_tm->tm_mday);
cmdsmv[i-1].append(buf);
cmdsmv[i-1].append("-");
sprintf(buf,"%d",now_tm->tm_hour);
cmdsmv[i-1].append(buf);
cmdsmv[i-1].append(":");
sprintf(buf,"%d",now_tm->tm_min);
cmdsmv[i-1].append(buf);
cmdsmv[i-1].append(":");
sprintf(buf,"%d",now_tm->tm_sec);
cmdsmv[i-1].append(buf);
cmdsmv[i-1].append(".");
sprintf(buf,"%d",int(now));
cmdsmv[i-1].append(buf);
}
cout<<cmdsmv[i-1]<<endl;
if(exec(cmdsmv[i-1].c_str(),true)){
iCountSuc +=1;
continue;
}
iCountFail+=1;
string err;
err.append(mv);
err.append(argv[i]);
err.append(fail);
errs[iCountFail]=err;
}
if(iCountSuc>=0){
for(string& imv:cmdsmv) cout<<imv<<" success1"<<endl;
}
if(iCountFail>=0){
// for(string& irr:errs)cout<<irr<<endl; // 发生错误时system(cmd)会打印标准错误的
}
string res;
res.append("total ");
char str[BUF_SIZE];
sprintf(str, "%d", iCountSuc+1);
res.append(str);
res.append(" success2");
if(iCountFail>=0 || iCountSuc<0){
res.append(", ");
sprintf(str, "%d", iCountFail+1);
res.append(str);
res.append(fail);
}
cout<<res<<endl;
return 0;
}
2、CMakeLists.txt:
cmake_minimum_required(VERSION 3.21)
project(rrm)
set(CMAKE_CXX_STANDARD 11)
add_executable(rrm rrm.cpp)
2.5、再给个VScode的编译任务设置tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label":"cd",
"type":"shell",
"command":"cd",
"args":[
"${fileDirname}/build"
],
"problemMatcher":"$gcc",
},
{
"label":"cmake ..",
"type":"shell",
"command":"cmake",
"args":[
// ".."
"${fileDirname}",
],
"problemMatcher":"$gcc",
},
{
"label":"cmake --build .",
"type":"shell",
"command":"cmake",
"args":[
"--build",
// "."
"${fileDirname}/build",
],
"dependsOrder":"sequence",
"dependsOn":[
"cd", // VScode dependsOn依赖任务的cd <cwd>对后序任务无影响,每次任务的cwd都位于${workspaceFolder}
"cmake .."
],
"problemMatcher":"$gcc",
},
]
}
注意到tasks.json每个任务的执行都是相互独立、不影响的,既便通过"dependsOn"设置依赖的任务列表并开启"dependsOrder"指定执行顺序。比如上面先执行"cd"任务将cwd切换到${fileDirname}/build,后执行"cmake .."命令,则"cmake .."命令的cwd并不相应地保持在${fileDirname}/build,每个任务执行的cwd都初始位于${workspaceFolder}。幸好cmake和cmake --build命令提供<cwd>选项可以直接指定工作目录,所以直接写绝对路径就可以。
这个CMakeLists.txt等价于:
mkdir build
cd build
cmake ..
camke --build .
编译出rrm可执行文件
3、查看$PATH
haypin@MBP ~ echo $PATH
/Users/haypin/.local/bin
:/Applications/CMake.app/Contents/bin
:/Users/haypin/Go1201/bin
:/Users/haypin/Go/bin
:/Users/haypin/miniconda3/condabin
:/Library/Frameworks/Python.framework/Versions/2.7/bin
:/usr/local/bin
:/usr/bin
:/bin
:/usr/sbin
:/sbin
:/Applications/VMware Fusion.app/Contents/Public
:/usr/local/go/bin
:/usr/local/share/dotnet
:/Library/Apple/usr/bin
:/Library/Frameworks/Mono.framework/Versions/Current/Commands
:/usr/local/mysql-8.0.21-macos10.15-x86_64/bin
haypin@MBP ~ which rm
/bin/rm
系统rm命令在/bin目录,那将自己写的rrm链接到$PATH比/bin更靠前的路径就可以被优先找到,我选择在/Users/haypin/.local/bin目录下链接自己写的rrm:
haypin@MBP ~ cd ~/.local/bin
haypin@MBP ~/.local/bin ln /Users/haypin/cpp_cmake_js_java_python/rrm/build/rrm rm
haypin@MBP ~/.local/bin ll rm
-rwxr-xr-x 1 haypin staff 56K 8 10 10:29 rm
关闭当前终端后再打开一个:
haypin@MBP ~ which rm
/Users/haypin/.local/bin/rm
此时的rm命令就是最先找到的自己写的rrm了。
4、测试
haypin@MBP ~/cpp_cmake_js_java_python/rrm touch robot
haypin@MBP ~/cpp_cmake_js_java_python/rrm rm robot
mv robot /Users/haypin/.Trash success
total 1 success
haypin@MBP ~/cpp_cmake_js_java_python/rrm cd ~/.Trash
haypin@MBP ~/.Trash ll
total 0
-rw-r--r-- 1 haypin staff 0B 8 10 11:21 robot
haypin@MBP ~/.Trash
5、尽情地rm吧,妈妈再也不怕我翻车了