How can I change permissions to 0777, at runtime, of a folder and all its subfolders, recursively?
The code is in c , mac. I'm including <sys/stat.h> which has chmod
, however there's no documentation on how to do it recursively.
CodePudding user response:
The simplest and most portable way would be to use the std::filesystem
library that was added in C 17. In there, you'll find a recursive_directory_iterator
and many other handy classes and functions for dealing with filesystem specific things.
Example:
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
void chmodr(const fs::path& path, fs::perms perm) {
fs::permissions(path, perm); // set permissions on the top directory
for(auto& de : fs::recursive_directory_iterator(path)) {
fs::permissions(de, perm); // set permissions
std::cout << de << '\n'; // debug print
}
}
int main() {
chmodr("your_top_directory", fs::perms::all); // perms::all = 0777
}
However, recursive_directory_iterator
has an issue when there are too many directories involved. It may run out of file descriptors because it needs to keep many directories open. For that reason, I prefer to use a directory_iterator
instead - and collect the subdirectories to examine for later.
Example:
#include <filesystem>
#include <iostream>
#include <vector>
namespace fs = std::filesystem;
void chmodr(const fs::path& path, fs::perms perm) {
std::vector<fs::path> subdirs;
fs::permissions(path, perm);
for(auto& de : fs::directory_iterator(path)) {
// save subdirectories for later:
if(fs::is_directory(de)) subdirs.push_back(de);
else fs::permissions(de, perm);
}
// now go through the subdirectories:
for(auto& sd : subdirs) {
chmodr(sd, perm);
}
}
int main() {
chmodr("your_top_directory", fs::perms::all);
}
You can read about the std::filesystem::
(fs::
in the code above) functions, classes and permission enums used in the example in the link I provided at the top.
In some implementations, with only partial C 17 support, you may find filesystem
in experimental/filesystem
instead. If that's the case, you can replace the above
#include <filesystem>
namespace fs = std::filesystem;
with the #ifdef
jungle I've provided in this answer.