之前写的跨平台命令是用C#的DotNetCore实现的,驱动程序需要dotnet “程序” 来驱动,还需要DotNetCore运行时。最近一直在自学C/C++跨平台开发,就拿Linux的tree命令当个练习,实现简单的tree效果。
代码如下:
#include
#include
#include
#include
//引用命名空间
using namespace std;
#ifdef _WIN32
#include
#include
#else
#include
#include
#include
#include
#endif
///
/// 用数列出目录
///
/// 目录
/// 层级
void TreeDir(const string dir, int level);
///
/// 得到当前系统目录对应linux的pwd
///
/// 当前系统工作目录
string GetSystemCurrentPath()
{
char buf[1024] = "";
string path = string();
#ifdef _WIN32
getcwd(buf, sizeof(buf));
regex reg("\\\\");
path = regex_replace(buf, reg, "/");
#else
getcwd(buf, sizeof(buf));
path = string(buf);
#endif
return path;
}
///
/// 主方法
///
/// 参数个数
/// 参数数组
///
int main(int argc, char* argv[])
{
string dir;
//有参数就按参数传
if (argc > 1)
{
for (int i = 1; i < argc; i++)
{
dir = argv[i];
TreeDir(dir, 0);
}
}
else
{
//否则当前路径
dir = GetSystemCurrentPath();
cout << "当前工作路径:" << dir << endl;
TreeDir(dir, 0);
}
return 0;
}
#ifdef _WIN32
///
/// 用数列出目录的东西
///
/// 目录
/// 层级
void TreeDir(const string dir, int level)
{
string dirNew = dir;
// 在目录后面加上"\\*.*"进行第一次搜索
dirNew += "\\*.*";
//句柄
intptr_t handle;
//文件结构体数据
_finddata_t findData;
//查询第一个到结构体
handle = _findfirst(dirNew.c_str(), &findData);
if (level == 0)
{
cout << "." << endl;
}
if (handle == -1)
{
cout << dir << "下没找到东西!" << endl;
return;
}
//遍历
do
{
//是子目录
if (findData.attrib & _A_SUBDIR)
{
if (strcmp(findData.name, ".") == 0 || strcmp(findData.name, "..") == 0)
{
continue;
}
string levelStr = "|";
if (level > 0)
{
for (int i = 0; i < level; i++)
{
levelStr += " ";
}
levelStr += "└── ";
}
cout << levelStr << "\033[34m" << findData.name << "\033[0m" << endl;
dirNew = dir + "\\" + findData.name;
// 在目录后面加上"\\"和搜索到的目录名进行下一次搜索
TreeDir(dirNew, ++level);
}
else
{
string levelStr = "|";
if (level > 0)
{
for (int i = 0; i < level; i++)
{
levelStr += " ";
}
levelStr += "└── ";
}
cout << levelStr << findData.name << "\t\033[31m " << findData.size << " bytes\033[0m \033[33m" << (findData.size * 1.0 / 1048576) << "兆\033[0m" << endl;
}
} while (_findnext(handle, &findData) == 0);
// 关闭搜索句柄
_findclose(handle);
}
#else
///
/// 判断路径是否是文件夹
///
/// 路径
/// 返回值
int PathIsDir(const char* path) {
struct stat st;
stat(path, &st);
if (S_ISDIR(st.st_mode)) {
return 1;
}
else {
return 0;
}
}
///
/// 得到文件的大小
///
/// 文件路径
///
int GetFileSize(const char* fname)
{
struct stat statbuf;
if (stat(fname, &statbuf) == 0)
{
return statbuf.st_size;
}
return -1;
}
///
/// 用数列出目录的东西
///
/// 目录
/// 层级
void TreeDir(const string dir, int level)
{
DIR* dirptr = NULL;
struct dirent* entry;
string dirNew;
if (level == 0)
{
cout << "." << endl;
}
if ((dirptr = opendir(dir.c_str())) == NULL)
{
cout << dir << "下没找到东西!" << endl;
return;
}
else
{
while (entry = readdir(dirptr))
{
dirNew = dir + "/" + entry->d_name;
//是子目录
if (PathIsDir(dirNew.c_str()) == 1)
{
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
{
continue;
}
string levelStr = "|";
if (level > 0)
{
for (int i = 0; i < level; i++)
{
levelStr += " ";
}
levelStr += "└── ";
}
cout << levelStr << "\033[34m" << entry->d_name << "\033[0m" << endl;
// 在目录后面加上"//"和搜索到的目录名进行下一次搜索
TreeDir(dirNew, ++level);
}
else
{
string levelStr = "|";
if (level > 0)
{
for (int i = 0; i < level; i++)
{
levelStr += " ";
}
levelStr += "└── ";
}
int fileSize = GetFileSize(dirNew.c_str());
cout << levelStr << entry->d_name <<" "<< fileSize << " bytes\033[0m \033[33m " << (fileSize * 1.0 / 1048576) << "兆\033[0m" << endl;
}
}
closedir(dirptr);
}
}
#endif
把代码上传到linux下编译
[root@zlzlinux ztree]# ls
CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt Makefile out ztree ztree.cpp ztree.h
[root@zlzlinux ztree]# cmake /zlz/ztree
-- Configuring done
-- Generating done
-- Build files have been written to: /zlz/ztree
[root@zlzlinux ztree]# make
[100%] Built target ztree
[root@zlzlinux ztree]# ls
CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt Makefile out ztree ztree.cpp ztree.h
[root@zlzlinux ztree]# ./ztree
当前工作路径:/zlz/ztree
.
|CMakeLists.txt333 bytes 0.000317574兆
|ztree.cpp4666 bytes 0.00444984兆
|ztree.h191 bytes 0.000182152兆
|.vs
| └── CMake Overview0 bytes 0兆
| └── ProjectSettings.json44 bytes 4.19617e-05兆
| └── slnx.sqlite122880 bytes 0.117188兆
| └── ztree
| └── v16
| └── Browse.VC.db18132992 bytes 17.293兆
| └── .suo31744 bytes 0.0302734兆
| └── Browse.VC.db-shm32768 bytes 0.03125兆
| └── Browse.VC.db-wal0 bytes 0兆
| └── Browse.VC.opendb0 bytes 0兆
| └── ipch
| └── AutoPCH
| └── 89671f735ddcda9b
| └── ZTREE.ipch36241408 bytes 34.5625兆
| └── out
| └── build
| └── x64-Debug
| └── .ninja_deps764 bytes 0.000728607兆
| └── .ninja_log5655 bytes 0.00539303兆
| └── build.ninja36596 bytes 0.0349007兆
| └── CMakeCache.txt15237 bytes 0.0145311兆
| └── cmake_install.cmake1526 bytes 0.00145531兆
| └── VSInheritEnvironments.txt12 bytes 1.14441e-05兆
| └── ztree.exe300544 bytes 0.286621兆
| └── ztree.ilk7888240 bytes 7.52281兆
| └── ztree.pdb5804032 bytes 5.53516兆
| └── CMakeFiles
| └── cmake.check_cache86 bytes 8.2016e-05兆
| └── CMakeOutput.log2971 bytes 0.00283337兆
| └── rules.ninja3005 bytes 0.00286579兆
| └── TargetDirectories.txt280 bytes 0.000267029兆
| └── 3.20.21032501-MSVC_2
| └── CMakeCCompiler.cmake2715 bytes 0.00258923兆
| └── CMakeCXXCompiler.cmake5706 bytes 0.00544167兆
| └── CMakeDetermineCompilerABI_C.bin51200 bytes 0.0488281兆
| └── CMakeDetermineCompilerABI_CXX.bin51200 bytes 0.0488281兆
| └── CMakeRCCompiler.cmake276 bytes 0.000263214兆
| └── CMakeSystem.cmake395 bytes 0.000376701兆
| └── CompilerIdC
| └── CMakeCCompilerId.c23315 bytes 0.0222349兆
| └── CMakeCCompilerId.exe96256 bytes 0.0917969兆
| └── CMakeCCompilerId.obj1827 bytes 0.00174236兆
| └── tmp
| └── CompilerIdCXX
| └── CMakeCXXCompilerId.cpp23157 bytes 0.0220842兆
| └── CMakeCXXCompilerId.exe96768 bytes 0.0922852兆
| └── CMakeCXXCompilerId.obj1848 bytes 0.00176239兆
| └── tmp
| └── CMakeTmp
| └── ShowIncludes
| └── foo.h2 bytes 1.90735e-06兆
| └── main.c33 bytes 3.14713e-05兆
| └── main.obj662 bytes 0.000631332兆
| └── ztree.dir
| └── embed.manifest406 bytes 0.000387192兆
| └── intermediate.manifest381 bytes 0.00036335兆
| └── manifest.rc194 bytes 0.000185013兆
| └── manifest.res472 bytes 0.000450134兆
| └── vc140.pdb626688 bytes 0.597656兆
| └── ztree.cpp.obj1579581 bytes 1.50641兆
| └── Testing
| └── Temporary
| └── LastTest.log142 bytes 0.000135422兆
| └── .cmake
| └── api
| └── v1
| └── reply
| └── cache-v2-51a68bf1555668097ad6.json23082 bytes 0.0220127兆
| └── cmakeFiles-v1-29619b4b17789c977400.json34573 bytes 0.0329714兆
| └── codemodel-v2-a6722adfd3bd9569793c.json959 bytes 0.000914574兆
| └── index-2021-10-16T02-21-35-0514.json2701 bytes 0.00257587兆
| └── target-ztree-Debug-0474d05d5df37210739b.json1690 bytes 0.00161171兆
| └── toolchains-v1-8de56aa7a78a76cb4021.json1368 bytes 0.00130463兆
| └── query
| └── client-MicrosoftVS
| └── query.json144 bytes 0.000137329兆
| └── CMakeFiles
| └── CMakeOutput.log36983 bytes 0.0352697兆
| └── 3.18.2
| └── CMakeSystem.cmake446 bytes 0.000425339兆
| └── CompilerIdC
| └── tmp
| └── CMakeCCompilerId.c20332 bytes 0.0193901兆
| └── a.out17448 bytes 0.0166397兆
| └── CompilerIdCXX
| └── tmp
| └── CMakeCXXCompilerId.cpp20152 bytes 0.0192184兆
| └── a.out17456 bytes 0.0166473兆
| └── CMakeDetermineCompilerABI_C.bin17280 bytes 0.0164795兆
| └── CMakeCCompiler.cmake2330 bytes 0.00222206兆
| └── CMakeDetermineCompilerABI_CXX.bin17296 bytes 0.0164948兆
| └── CMakeCXXCompiler.cmake5357 bytes 0.00510883兆
| └── CMakeTmp
| └── cmake.check_cache85 bytes 8.10623e-05兆
| └── ztree.dir
| └── depend.make145 bytes 0.000138283兆
| └── link.txt56 bytes 5.34058e-05兆
| └── cmake_clean.cmake235 bytes 0.000224113兆
| └── build.make3690 bytes 0.00351906兆
| └── DependInfo.cmake532 bytes 0.000507355兆
| └── flags.make179 bytes 0.000170708兆
| └── progress.make43 bytes 4.1008e-05兆
| └── CXX.includecache276 bytes 0.000263214兆
| └── depend.internal155 bytes 0.00014782兆
| └── ztree.cpp.o14144 bytes 0.0134888兆
| └── CMakeDirectoryInformation.cmake596 bytes 0.00056839兆
| └── TargetDirectories.txt109 bytes 0.000103951兆
| └── progress.marks2 bytes 1.90735e-06兆
| └── Makefile23382 bytes 0.00322533兆
| └── Makefile.cmake1883 bytes 0.00179577兆
| └── CMakeCache.txt13675 bytes 0.0130415兆
| └── Makefile5014 bytes 0.00478172兆
| └── cmake_install.cmake1590 bytes 0.00151634兆
| └── ztree34216 bytes 0.0326309兆
[root@zlzlinux ztree]#
把编译程序拷贝到usr/bin下
[root@zlzlinux ztree]# ls /usr
bin games include lib lib64 libexec local sbin share src tmp
[root@zlzlinux ztree]# cp /zlz/ztree/ztree /usr/bin/ztree
[root@zlzlinux ztree]# cd /zzh
[root@zlzlinux zzh]# ztree
当前工作路径:/zzh
.
|2554 bytes 5.14984e-05兆
|1815 bytes 1.43051e-05兆
|baba
| └── 181 bytes 7.72476e-05兆
| └── 2341 bytes 0.000325203兆
| └── mama
| └── 5439 bytes 8.58307e-06兆
| └── tt451 bytes 0.000430107兆
| └── .zzhcd.swp12288 bytes 0.0117188兆
| └── zzhcd202 bytes 0.000192642兆
[root@zlzlinux zzh]# tree
.
├── 18
├── 25
├── 543
├── baba
│ ├── 1
│ └── 2
├── mama
├── tt
└── zzhcd
2 directories, 7 files
[root@zlzlinux zzh]#
[root@zlzlinux zzh]# cd /zlz
[root@zlzlinux zlz]# ztree /zzh
.
|2554 bytes 5.14984e-05兆
|1815 bytes 1.43051e-05兆
|baba
| └── 181 bytes 7.72476e-05兆
| └── 2341 bytes 0.000325203兆
| └── mama
| └── 5439 bytes 8.58307e-06兆
| └── tt451 bytes 0.000430107兆
| └── .zzhcd.swp12288 bytes 0.0117188兆
| └── zzhcd202 bytes 0.000192642兆
[root@zlzlinux zlz]#
这样就用C++实现了一版简化的tree命令。麻烦点就是在windows下看不到linux下头文件,写预编译命令时候有点摸黑的感觉,来回上传代码编译。不过可以用Linux桌面在VSCode写Linux实现部分。