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.