comparative review – Basic Linux Commands Recreation (filesystem) In C++

Hey I’m learning the file system library and thought nothing could be better than a project so i thought of recreating the basic linux command like ls, cd etc through c++ and file system.As i said I’m learning c++ and exploring libraries there would be many weird code and all those things,could you review my code and say where i can improve the code.

My Code :

main.cpp

#include <iostream>
#include <filesystem>
#include "command.h"
namespace fs = std::filesystem;
int main()
{
    //Basic Linux Feel ;)
    std::string CurPath = fs::current_path();
    std::cout << "~";
    color::color_blue(CurPath);
    std::cout << "$ ";
    //Main Loop
    while (true)
    {
        std::string cmnd;
        getline(std::cin, cmnd);
        #if DEBUG
                if (cmnd == "exit")
                    return 0;
        #endif
        DetermineCommand(cmnd);
    }
}

command.h

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <chrono>
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
using namespace std::chrono_literals;
//DEBUG Mode :) I Used This For Exitting The Infinite Loop
#define DEBUG 1

//Used For Setting Color To Console According To OS
class color
{
  public:
    static void color_green(std::string path)
    {
#ifndef __LINUX
        //color code for green
        std::cout << "33(32m" << path << "33(0m";
#else
        //Green
        system("Color 02");
        std::cout << path;
        //White
        system("Color 07");
#endif
    }
    static void color_blue(std::string path)
    {
//color code for blue
#ifndef __LINUX
        std::cout << "33(34m" << path << "33(0m";
#else
        //Blue
        system("Color 01");
        std::cout << path << " ";
        //White
        system("Color 07");
#endif
    }
};
//Says The Current Path Color Encoded
void SayPath()
{
    std::cout << std::endl;
    std::string CurPath = fs::current_path();
    std::cout << "~";
    color::color_blue(CurPath);
    std::cout << "$ ";
}
//cp Used For Copying Files
void cp(std::string p1, std::string p2)
{
    fs::path ToCopy = p1, Target = p2;
    if (!fs::exists(p2)|| !fs::exists(p1))
    {
        throw std::string("cp: cannot stat " + p1 + ": No such file or directory");
    }
    //Trying To Warn
    fs::path CheckExist = p2 + "/" + p1;
    if (exists(CheckExist))
    {
        std::cout << "The File Already Exist On The Given Path Replace Them (Y/N) ";
        char ans;
        std::cin >> ans;
        if (ans != 'Y' || ans != 'y')
        {
            std::cout << "Aborted!";
            return;
        }
    }
    fs::copy(p1, p2, fs::copy_options::recursive);
}
//mkdir Used For Making Directories
void mkdir(std::string &s)
{
    fs::create_directories(s);
}

//rm Used For Deleteing Files
void rm(std::string s)
{
    std::error_code err;
    //Handling The Case If Directory Doesn't Exsist
    if (!fs::exists(s))
    {
        throw std::string("rm: cannot remove '" + s + "': No such file or directory");
    }
    if (fs::is_directory(s, err))
    {
        if (fs::exists(s))
        {
            throw std::string("rm: cannot remove '" + s + "': Is a directory");
        }
    }
    fs::remove(s);
    return;
}

//The “cd” Command Used For Navigating Over Directories
void cd(std::string &path)
{
    //cd .. implementation - going to parent directory
    if (path == "..")
    {
        fs::path Parent = fs::current_path().parent_path();
        fs::current_path(Parent);
        return;
    }
    //If The User Entered A Blank Path Or Just The "cd" command
    else if (path == "")
    {
        fs::current_path(fs::current_path().root_directory());
        return;
    }
    //If Path Doesn't Exist
    else if (!fs::exists(path))
    {
        throw std::string("cd: " + path + " No such file or directory");
    }
    else
    {
        fs::current_path(path);
    }
}

//The “ls” Command Is Used For Printing All The Files And Directories In The Cirrent Folder
void ls()
{
    fs::path CurPath = fs::current_path();
    //f_name will be used for storing paths and names
    std::string f_name;
    for (auto &Name : fs::directory_iterator(CurPath))
    {
        //If It's A File
        std::error_code err;
        if (fs::is_regular_file((Name).path(), err))
        {
            f_name = Name.path().filename();
            color::color_green(f_name);
            std::cout << " ";
        }
        //If It's A Folder
        else
        {
            f_name = Name.path().filename();
            color::color_blue(f_name);
            std::cout << " ";
        }
    }
}
//mv move command
void mv(std::string From, std::string To, bool IsRename)
{
    fs::path p1 = From, p2 = To;
    //Checking If It's For Renaming
    if (!IsRename)
    {
        fs::path CheckExist = To + "/" + From;
        if (exists(CheckExist))
        {
            std::cout << "The File Already Exist On The Given Path Replace Them (Y/N) ";
            char ans;
            std::cin >> ans;
            if (ans != 'Y' || ans != 'y')
            {
                std::cout << "Aborted!";
                return;
            }
        }
    }
    fs::copy(From, To);
    fs::remove(From);
}
void rmdir(std::string Path){
    if(!fs::exists(Path)){
        throw std::string("rmdir: failed to remove "+Path+": No such file or directory");
    }
    if(!fs::is_directory(Path)){
        throw std::string("rmdir: failed to remove "+Path+": Not a directory");
    }
    fs::remove(Path);
}
//Related To File Information
std::streampos GetSize(std::string PathName){
    std::streampos FullSize=0;
    fs::path Path=PathName;
    if(fs::is_directory(Path)){
        for (auto& Name:fs::recursive_directory_iterator(Path)){
            if(fs::is_regular_file(Name.path())){
                std::ifstream Open(Name.path(),std::ios_base::binary);
                std::streampos ThisSize=Open.tellg();
                Open.seekg(0,std::ios::end);
                FullSize+=ThisSize-Open.tellg();
                Open.close();
            }
        }
        return FullSize;
    }
    else{
        std::ifstream Open(Path);
        std::streampos ThisSize=Open.tellg();
        Open.seekg(0,std::ios::end);
        ThisSize=ThisSize-Open.tellg();
        Open.close();
        return ThisSize;
    }
}
void PrintTime(std::string Path){
    //Copied From Runebook.dev ;)
    auto ftime=fs::last_write_time(Path);
    std::time_t cftime = decltype(ftime)::clock::to_time_t(ftime);
    std::cout <<std::asctime(std::localtime(&cftime));
}
void GetInfo(std::string Path){
    if(!fs::exists(Path)){
        throw std::string("--info: "+Path+" No such file or directory");
    }
    std::streampos Size=GetSize(Path);
    std::cout<<"SIZE : "<<Size<<std::endl;
    std::cout<<"PATH : "<<Path<<std::endl;
    std::cout<<"LAST MODIFIED : "; 
    PrintTime(Path);
    if(fs::is_directory(Path)){
        std::cout<<"TYPE : Directory";
    }
    else{
        std::cout<<"TYPE : File";
    }
}
void cat(std::string Path){
    if(!fs::exists(Path)){
        throw std::string("cat: "+Path+": No such file or directory");
    }
    else if(fs::is_directory(Path)){
        throw std::string("cat: "+Path+": Is a directory");
    }
    std::string Temp;
    std::ifstream Reader(Path);
    while(getline(Reader,Temp)){
        std::cout<<Temp<<std::endl;
    }
}
void help(){
    std::cout<<"•cdn•lsn•mkdirn•rmdirn•rmn•pwdn•echon•clearn•cpn•mvn•renamen•--infon•cat";
    SayPath();
}
//This Function Is Used For Determining The Type Of Command
void DetermineCommand(std::string &s)
{
    std::stringstream Extractor(s);
    std::string Type;
    Extractor >> Type;
    if (Type == "cd")
    {
        if (s.length() == 2 || s(3) == ' ')
        {
            std::string Empty = "";
            cd(Empty);
            SayPath();
            return;
        }
        //I'm Reusing The Type Variable To Store The Path As The Next Would Be The Path
        Extractor >> Type;
        try
        {
            cd(Type);
            SayPath();
        }
        catch (std::string Error)
        {
            std::cout << Error;
            SayPath();
            return;
        }
    }
    else if (Type == "ls")
    {
        ls();
        SayPath();
    }
    else if (Type == "mkdir")
    {
        std::string Path;
        Extractor >> Path;
        mkdir(Path);
        SayPath();
    }
    else if (Type == "rm")
    {
        std::string Parms;
        Extractor >> Parms;
        try
        {
            rm(Parms);
            std::cout << "b";
        }
        catch (std::string Error)
        {
            std::cout << Error;
        }
        SayPath();
    }
    else if (Type == "pwd")
    {
        std::cout << fs::current_path();
        SayPath();
    }
    else if (Type == "echo")
    {
        std::string s;
        std::string a;
        Extractor>>s;
        while(Extractor>>a){
            s+=a+' ';
        }
        if(s(0)=='"' && s(s.length()-1)=='"'){
            s.erase(s.begin());
            s.erase(s.end());
        }
        std::cout << s;
        SayPath();
    }
    else if (Type == "clear")
    {
        system("clear");
        SayPath();
    }
    else if (Type == "cp")
    {
        std::string p1, p2;
        Extractor >> p1 >> p2;
        try
        {
            cp(p1, p2);
        }
        catch (std::string Err)
        {
            std::cout << Err;
        }
        SayPath();
    }
    else if (Type == "mv")
    {
        std::string p1, p2;
        Extractor >> p1 >> p2;
        try{
            mv(p1, p2, false);
        }
        catch(...){
            std::cout<<"Some Error Occuredn";
        }
        std::cout<<'b';
        SayPath();
    }
    else if (Type == "rename")
    {
        std::string p1, p2;
        Extractor >> p1 >> p2;
        mv(p1, p2, true);
        std::cout<<'b';
        SayPath();
    }
    else if(Type=="--info"){
        try{
            std::string Path;
            Extractor>>Path;
            GetInfo(Path);
            //Flushing n
            std::cout<<'b';
            SayPath();
        }
        catch(std::string err){
            std::cout<<err;
            SayPath();
        }
    }
    else if(Type == "cat"){
        std::string FName;
        Extractor>>FName;
        try{
            cat(FName);
        }
        catch(std::string err){
            std::cout<<err<<std::endl;
        }
        std::cout<<'b';
        SayPath();
    }
    else if(Type=="--help"){
        help();
    }
    else if(Type == "rmdir"){
        std::string Path;
        Extractor>>Path;
        rmdir(Path);
        SayPath();
    }
    else{
        std::cout<<"No such command found use --help to get a list of all command";
        SayPath();
    }
}

If youre having problem seeing the code i have uploaded it on GitHub Too – Repo

Note – i didn’t implemented all versions of every command like for example i just implemented ls not other version like ls -a etc

Thanks for checking this out!!