1+ #include < filesystem>
12#include < algorithm>
23#include < iostream>
34#include < iomanip>
78#include < numeric>
89#include < string>
910#include < vector>
11+ #include < cctype>
1012 // HighFive API
1113#include < H5Cpp.h>
1214#include < highfive/highfive.hpp>
@@ -638,17 +640,66 @@ namespace PR {
638640 else return 0 ;
639641 }
640642 }
643+
644+ std::vector<std::string>
645+ ParticleReader::scanDirectory (const std::string& dir)
646+ {
647+ // Will contain the filenames from the directory scan
648+ std::vector<std::string> ret;
649+
650+ // Check if the directory exists
651+ std::filesystem::path p (dir);
652+
653+ // If the directory does not exist, ret will be returned with zero
654+ // length
655+ if (std::filesystem::is_directory (p)) {
656+
657+ // Iterate over the directory entries
658+ for (const auto & entry : std::filesystem::directory_iterator (p)) {
659+
660+ // Check if the entry is a regular file
661+ if (std::filesystem::is_regular_file (entry.status ())) {
662+
663+ // Get the filename
664+ std::string filename = entry.path ().string ();
665+
666+ // Check if the last character is a digit
667+ if (std::isdigit (filename.back ())) {
668+
669+ // Assume that this is a snapshot file. We could check if
670+ // this is HDF5 here but I'd rather that this procedure be
671+ // file-type agnostic.
672+ ret.push_back (filename);
673+ }
674+ }
675+ }
676+ }
677+
678+ return ret;
679+ }
641680
642-
681+
643682 PSPhdf5::PSPhdf5 (const std::vector<std::string>& files, bool verbose)
644683 {
645684 _files = files;
646685 _verbose = verbose;
647686
687+ // Do we have a directory of snapshot files?
688+ //
689+ if (_files.size ()==1 ) {
690+ std::vector<std::string> fscan = scanDirectory (_files[0 ]);
691+ if (fscan.size () != 0 ) _files = fscan;
692+ // Put the first file at the top of the list
693+ std::partial_sort (_files.begin (), _files.begin ()+1 , _files.end ());
694+ }
695+
696+ // Read metadata from the first file
697+ //
648698 getInfo ();
649699
650700 // Sanity check
651- if (nfiles != files.size ())
701+ //
702+ if (nfiles != _files.size ())
652703 throw GenericError (" PSPhdf5: number of files does not match number expected for this snapshot" , __FILE__, __LINE__, 1042 , true );
653704
654705 curfile = _files.begin ();
@@ -1832,6 +1883,28 @@ namespace PR {
18321883 return parseStringList (files, delimit);
18331884 }
18341885
1886+ // Are all the files in the list directories?
1887+ bool
1888+ ParticleReader::parseDirectoryList (const std::vector<std::string>& files)
1889+ {
1890+ int dcount = 0 ; // The directory count
1891+ int fcount = 0 ; // The file count
1892+
1893+ for (auto f : files) {
1894+ if (std::filesystem::is_directory (f))
1895+ dcount++;
1896+ else
1897+ fcount++;
1898+ }
1899+
1900+ if (dcount>0 and fcount>0 )
1901+ throw std::runtime_error (" ParticleReader::parseDirectoryList: "
1902+ " cannot mix directories and files" );
1903+
1904+ return dcount>0 ;
1905+ }
1906+
1907+
18351908 std::vector<std::vector<std::string>>
18361909 ParticleReader::parseStringList
18371910 (const std::vector<std::string>& infiles, const std::string& delimit)
@@ -1842,6 +1915,14 @@ namespace PR {
18421915 auto files = infiles;
18431916 std::sort (files.begin (), files.end ());
18441917
1918+ // Check to see if these are all directories
1919+ if (parseDirectoryList (files)) {
1920+ for (auto d : files) {
1921+ batches.push_back (std::vector<std::string>{d});
1922+ }
1923+ return batches;
1924+ }
1925+
18451926 std::vector<std::string> batch;
18461927 std::string templ;
18471928
0 commit comments