C++第一个跨平台命令ztree练习

20 篇文章 0 订阅
这篇博客介绍了如何使用C++编写一个跨平台的tree命令,分别针对Windows和Linux系统实现了目录树的遍历。代码中包含了适配不同系统的头文件和函数,通过递归调用来展示目录结构。博主在Linux环境下编译并测试了代码,能够正确显示目录及文件信息。
摘要由CSDN通过智能技术生成

之前写的跨平台命令是用C#的DotNetCore实现的,驱动程序需要dotnet “程序” 来驱动,还需要DotNetCore运行时。最近一直在自学C/C++跨平台开发,就拿Linux的tree命令当个练习,实现简单的tree效果。

代码如下:

#include <iostream>
#include <string>  
#include <cstring>  
#include <regex>
//引用命名空间
using namespace std;
#ifdef _WIN32
#include <io.h>
#include <direct.h>
#else
#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#endif


/// <summary>
/// 用数列出目录
/// </summary>
/// <param name="dir">目录</param>
/// <param name="level">层级</param>
void TreeDir(const string dir, int level);

/// <summary>
/// 得到当前系统目录对应linux的pwd
/// </summary>
/// <returns>当前系统工作目录</returns>
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;
}

/// <summary>
/// 主方法
/// </summary>
/// <param name="argc">参数个数</param>
/// <param name="argv">参数数组</param>
/// <returns></returns>
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
/// <summary>
/// 用数列出目录的东西
/// </summary>
/// <param name="dir">目录</param>
/// <param name="level">层级</param>
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
/// <summary>
/// 判断路径是否是文件夹
/// </summary>
/// <param name="path">路径</param>
/// <returns>返回值</returns>
int PathIsDir(const char* path) {
	struct stat st;
	stat(path, &st);
	if (S_ISDIR(st.st_mode)) {
		return 1;
	}
	else {
		return 0;
	}
}

/// <summary>
/// 得到文件的大小
/// </summary>
/// <param name="fname">文件路径</param>
/// <returns></returns>
int GetFileSize(const char* fname)
{
	struct stat statbuf;
	if (stat(fname, &statbuf) == 0)
	{
		return statbuf.st_size;
	}
	return -1;
}

/// <summary>
/// 用数列出目录的东西
/// </summary>
/// <param name="dir">目录</param>
/// <param name="level">层级</param>
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

windows下效果
在这里插入图片描述

把代码上传到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实现部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小乌鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值