Is there a simple way to strip away the starting ./ of a path. For example: I have a path ./x/y and i want to convert it to x/y (without the first dot and slash). Is there a standard way of doing it?
#include <iostream>
#include <filesystem>
namespace filesystem = std::filesystem;
int main() {
auto path = filesystem::path{"./x/y"};
std::cout << path << std::endl;
std::cout << ???? << std::endl; // How do I do this?
}
Apparently the problem could be solved with std::filesystem::relative():
#include <iostream>
#include <filesystem>
namespace filesystem = std::filesystem;
int main() {
auto path = filesystem::path{"./x"};
std::cout << path << std::endl;
std::cout << filesystem::relative(path, "./") << std::endl; //
}
Produces
"./x"
"x"
Related
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
using namespace std;
int main()
{
fs::path p = fs::current_path();
cout << p << endl;
string p_string = p.string();
cout << p_string << endl;
return 0;
}
When printing out 'p' the path is shown as this.
"C:\\Users\\tp\\source\\repos\\test"
But after the conversion to a string it comes out like this.
C:\Users\tp\source\repos\test
Is there a way I could retain the original form of the path?
From cppreference's page on operator<<(std::filesystem::path):
Performs stream input or output on the path p. std::quoted is used so that spaces do not cause truncation when later read by stream input operator.
So we'll get the same string by manually calling std::quoted:
#include <iostream>
#include <iomanip>
#include <filesystem>
namespace fs = std::filesystem;
using namespace std;
int main()
{
fs::path p = fs::current_path();
// Should be same
cout << p << endl;
cout << std::quoted(p.string());
return 0;
}
I have a C++ program that takes a directory, like "D:\P4Test", and attempts to tell me how many bytes are in each subfolder and file within that directory. The code I currently have looks like this:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <string>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdint>
#include <sstream>
#include <filesystem>
using namespace std;
namespace fs = std::filesystem;
using namespace std::filesystem;
int main()
{
string path = "D:\\P4Test";
for (const auto& entry : directory_iterator(path)) {
cout << entry.path() << std::endl;
uintmax_t fsize = file_size(entry.path());
cout << " ||| " << fsize << endl;
}
}
Yes, it has a lot of unnecessary includes and such, but that's for future things.
When I run this code, I don't get what I want. Here's a picture of what's in that directory, and the output.
As you can see, the output looks good, but it does not give me the bytes for what's in the folders called "Two" & "Three".
Both folders have a text file in them that's 5 bytes, but they report back 0.
Can anyone help me figure out why, and show me how to make the folders show their bytes, or direct me to where I can figure this out?
It looks like you are trying to do a recursive file size check, but you do not actually recurse into the directories. 1 way to do this is to stasrt with a function gets all of the file sizes:
void folder_size(std::filesystem::path path) {
for (const auto& entry : directory_iterator(path)) {
cout << entry.path() << std::endl;
uintmax_t fsize = file_size(entry.path());
cout << " ||| " << fsize << endl;
}
}
Now we simply a special case to deal with if the file type is a directory, we can do this with std::filesystem::directory_entry::is_directory:
if (entry.is_directory()) {
// Handle the directory
}
So how do we handle the directory, well we have a function that we made that takes a directory path and goes through it. Lets call that:
if (std::filesystem::is_directory(entry.path())) {
folder_size(entry.path())
}
Putting it all together:
void folder_size(std::filesystem::path path) {
for (const auto& entry : directory_iterator(path)) {
cout << entry.path() << std::endl;
uintmax_t fsize = file_size(entry.path());
cout << " ||| " << fsize << endl;
if (std::filesystem::is_directory(entry.path())) {
folder_size(entry.path())
}
}
}
NOTE: All of the above is example code. No compilation check has been conducted.
For last couple of days I have been experimenting the behavior of few of the functions of filesystem and experimental/filesystem library.
Note: I ran the code on https://godbolt.org/
below is the code snippet with its output
1. experimental/filesystem
#include <iostream>
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
int main()
{
auto p = fs::path("//net");
std::cout<<"p = " << p
<<"\np.root_name= "<< p.root_name()
<<"\nand p.root_Dir= "<< p.root_directory()
<<"\np.is_absolute= "<<p.is_absolute()<<std::endl;
}
output:
p = "//net"
p.root_name= "//net"
and p.root_Dir= ""
p.is_absolute= 0
2. filesystem
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
auto p = fs::path("//net");
std::cout<<"p = " << p
<<"\np.root_name= "<< p.root_name()
<<"\nand p.root_Dir= "<< p.root_directory()
<<"\np.is_absolute= "<<p.is_absolute()<<std::endl;
}
output:
p = "//net"
p.root_name= ""
and p.root_Dir= "/"
p.is_absolute= 1
Is there any way to look into the implementation of these functions ?
How to get a vector of directories/files and sub-directories in a specific path using modern C++?
Using a recursive function with std::filesystem..!
#if __cplusplus < 201703L// If the version of C++ is less than 17
// It was still in the experimental:: namespace
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
#include <filesystem>
namespace fs = std::filesystem;
#endif
std::vector<fs::path> geteverything(const fs::path &path)
{
std::vector<fs::path> dirs;
for (const auto & entry : fs::directory_iterator(path))
{
dirs.push_back(entry);
if (fs::is_directory(entry))
{
auto subdirs = geteverything(entry);
dirs.insert(dirs.end(), subdirs.begin(), subdirs.end());
}
}
return dirs;
}
Test
// Change this to the absolute/relative path you'd like to fetch.
std::string path = "C:/Windows/Temp";
int main()
{
std::cout << "fetching all directories and files in : " << path << " ...\n";
auto list = geteverything(path);
for (const auto &path : list)
std::cout << path << "\n";
return 0;
}
I am running through a directory containing multiple sub-directories. I am using recursive_directory_iterator. I have directory asr->collections->(multiple directories and couple of text files)
#include <iostream>
#include <filesystem>
#include <conio.h>
using namespace std::tr2::sys;
int main () {
std::string path_;
std::cout << " Enter the path ";
std::cin >> path_;
auto dir_path = path(path_);
for (auto it = directory_iterator(dir_path); it != directory_iterator(); ++it)
{
const auto& file = it->path();
std::cout << " path : " << file << std::endl;
if (is_directory (status(it->path())))
std::cout << " It is a directory. " << std::endl;
else
std::cout << " It is not a directory. " << std::endl;
}
_getch();
return 0;
}
I know I had posted this earlier. It was a silly mistake, I changed it. But it is still bugy. The issue I am having is the is-directory returns false for everything.
Am I using it wrong. I have linked the MSDN URL below.
I installed boost and ran the code. It worked !
Boost Source
#include <iostream>
#include <boost\filesystem.hpp>
#include <conio.h>
using namespace boost::filesystem;
int main () {
std::string path_;
std::cout << " Enter the path ";
std::cin >> path_;
auto dir_path = path(path_);
for (auto it = directory_iterator(dir_path); it != directory_iterator(); ++it)
{
const auto& file = it->path();
std::cout << " path : " << file << std::endl;
if (is_directory (status(it->path())))
std::cout << " It is a directory. " << std::endl;
else
std::cout << " It is not a directory. " << std::endl;
}
_getch();
return 0;
}
http://msdn.microsoft.com/en-us/library/hh874754.aspx
Also, can I use the boost filesystem documentation be used as a tutorial for this, since there is no good documentation as to what is what and how to use it.
if (is_directory (status(dir_path)) )
Yes, you are using it wrong. Try testing the file, not dir_path. You already know that dir_path is a directory.
Ok, the issue was fixed after I updated the Visual Studio with first major update.