I'm trying to make a CD command for a shell I call POSH (Pine's own shell).
If the previous cd command didn't end in a /, it will append the two paths and throw (cd pine then cd src will error because path would be /home/dingus/pinesrc instead of /home/dingus/pine/src).
I know why this happens, but can't seem to fix it.
Here is the source code:
inline void cd(string cmd)
{
if(cmd.length() < 3) return;
string arg = cmd.substr(3);
if(fs::is_directory(fs::status( string(path).append(arg))))
{
path.append(arg);
}
else cout << "Error: \"" << arg << "\" is not a directory" << endl;
}
CodePudding user response:
string(path).append(arg) is performing string concatenation. You are not appending any of your own slashes between filesystem elements. So, if the path is /home/dingus/, then cd pine would just append pine to the end producing /home/dingus/pine, and then cd src would just append src to the end producing /home/dingus/pinesrc, as you observed.
You would need to do something more like this instead:
string curr_path;
inline void cd(string cmd)
{
if (cmd.length() < 4) return;
string arg = cmd.substr(3);
string new_path = curr_path;
if ((!new_path.empty()) && (new_path.back() != '\\')) {
new_path = '\\';
}
new_path = arg;
if (fs::is_directory(fs::status(new_path))) {
curr_path = new_path;
}
else {
cout << "Error: \"" << arg << "\" is not a directory" << endl;
}
}
However, since you are using the <filesystem> library anyway, you should be using std::filesystem::path (especially since std::filesystem::status() only accepts std::filesystem::path to begin with). Let the library handle any path concatenations for you, eg:
fs::path curr_path;
inline void cd(string cmd)
{
if (cmd.length() < 4) return;
string arg = cmd.substr(3);
fs::path new_path = curr_path / arg;
if (fs::is_directory(new_path)) {
curr_path = new_path;
}
else {
cout << "Error: \"" << arg << "\" is not a directory" << endl;
}
}
std::filesystem::path implements operator/ to insert a slash if one is not already present.
