diff --git a/SimoxUtility/CMakeLists.txt b/SimoxUtility/CMakeLists.txt
index e1df435c0a85f6d65b7605969aff10b8193babfd..6b3a7603eb8fdac5b59491d4bf422c957d76e770 100644
--- a/SimoxUtility/CMakeLists.txt
+++ b/SimoxUtility/CMakeLists.txt
@@ -53,6 +53,8 @@ SET(SOURCES
     color/color.cpp
     color/GlasbeyLUT.cpp
 
+    filesystem/list_directory.cpp
+
     json/eigen_conversion.cpp
     json/io.cpp
     json/converters.cpp
@@ -72,6 +74,7 @@ SET(INCLUDES
 
     eigen/AssertAsException.h
 
+    filesystem/list_directory.h
     filesystem/remove_trailing_separator.h
 
     json.h
diff --git a/SimoxUtility/filesystem.h b/SimoxUtility/filesystem.h
index 68d083fd265169f8a51984201e6aff08dc97c842..f2b3aaed65813fe2b2d258f01fc02e7c4f4d3f8e 100644
--- a/SimoxUtility/filesystem.h
+++ b/SimoxUtility/filesystem.h
@@ -2,4 +2,5 @@
 
 // This file is generated!
 
+#include "filesystem/list_directory.h"
 #include "filesystem/remove_trailing_separator.h"
diff --git a/SimoxUtility/filesystem/list_directory.cpp b/SimoxUtility/filesystem/list_directory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..00ab3514bfe6a3eb355769f0b4cf5dcef4f2a697
--- /dev/null
+++ b/SimoxUtility/filesystem/list_directory.cpp
@@ -0,0 +1,32 @@
+#include "list_directory.h"
+
+#include <algorithm>
+
+
+namespace simox
+{
+    std::vector<fs::path> fs::list_directory(const path& directory, bool local, bool sort)
+    {
+        std::vector<path> entries;
+        for (const auto& entry : directory_iterator(directory))
+        {
+            entries.push_back(entry.path());
+        }
+
+        if (sort)
+        {
+            std::sort(entries.begin(), entries.end());
+        }
+
+        if (local)
+        {
+            for (auto& entry : entries)
+            {
+                entry = entry.filename();
+            }
+        }
+        return entries;
+    }
+
+}
+
diff --git a/SimoxUtility/filesystem/list_directory.h b/SimoxUtility/filesystem/list_directory.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0342d8c42e04c2bacbbf698f896f4d2b99a4ef4
--- /dev/null
+++ b/SimoxUtility/filesystem/list_directory.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <filesystem>
+#include <vector>
+
+
+namespace simox::fs
+{
+    using namespace std::filesystem;
+
+    /**
+     * @brief List the entries in directory `directory`.
+     * @param directory Path to the directory.
+     * @param local
+     *      If true, returned paths are relative to `directory`.
+     *      If false, the entries are prepended by `directory`.
+     * @param sort If true, entries are sorted alphatically.
+     * @return The entries in `directory`.
+     */
+    std::vector<path> list_directory(const path& directory, bool local = false, bool sort = true);
+}
+
diff --git a/SimoxUtility/tests/CMakeLists.txt b/SimoxUtility/tests/CMakeLists.txt
index 7dd6f10f521d6a69c635811222822d3725d66f32..62f8f9ccaeaddb4e6b88d556968852c56f4deba9 100644
--- a/SimoxUtility/tests/CMakeLists.txt
+++ b/SimoxUtility/tests/CMakeLists.txt
@@ -20,6 +20,8 @@ ADD_SU_TEST( ForEachIf )
 ADD_SU_TEST( JsonEigenConversionTest )
 ADD_SU_TEST( JsonIOTest )
 
+ADD_SU_TEST( filesystem_list_directory_test )
+
 ADD_SU_TEST( math_pose_invert_test )
 ADD_SU_TEST( math_pose_orthogonalize_test )
 ADD_SU_TEST( math_pose_pose_test )
diff --git a/SimoxUtility/tests/filesystem_list_directory_test.cpp b/SimoxUtility/tests/filesystem_list_directory_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..142d008918e2662432430d284641952c557f62c9
--- /dev/null
+++ b/SimoxUtility/tests/filesystem_list_directory_test.cpp
@@ -0,0 +1,82 @@
+/**
+* @package    VirtualRobot
+* @author     Rainer Kartmann
+* @copyright  2019 Rainer Kartmann
+*/
+
+#define BOOST_TEST_MODULE SimoxUtility_filesystem_list_directory_test
+
+#include <boost/test/included/unit_test.hpp>
+
+#include <SimoxUtility/filesystem/list_directory.h>
+
+#include <string>
+#include <stdio.h>
+#include <random>
+
+
+namespace fs = simox::fs;
+
+
+namespace
+{
+    struct Fixture
+    {
+        const fs::path directory = "filesystem_list_directory_test.dir";
+        std::vector<fs::path> filenames =
+        {
+            "file1", "file2.txt", "file3.txt.temp", "~file4", ".file5"
+        };
+
+        bool sort = true;
+
+
+        Fixture()
+        {
+            std::sort(filenames.begin(), filenames.end());
+
+            BOOST_REQUIRE(!std::filesystem::exists(directory));
+            std::filesystem::create_directories(directory);
+
+            for (auto file : filenames)
+            {
+                std::ofstream ofs(directory / file);
+                BOOST_REQUIRE(std::filesystem::exists(directory / file));
+            }
+        }
+        ~Fixture()
+        {
+            std::filesystem::remove_all(directory);
+            BOOST_REQUIRE(!std::filesystem::exists(directory));
+        }
+    };
+}
+
+
+BOOST_FIXTURE_TEST_SUITE(list_directory_test, Fixture)
+
+
+BOOST_AUTO_TEST_CASE(test_list_directory_local)
+{
+    bool local = true;
+    std::vector<fs::path> entries = fs::list_directory(directory, local, sort);
+
+    BOOST_CHECK_EQUAL_COLLECTIONS(entries.begin(), entries.end(), filenames.begin(), filenames.end());
+}
+
+BOOST_AUTO_TEST_CASE(test_list_directory_nonlocal)
+{
+    bool local = false;
+    std::vector<fs::path> entries = fs::list_directory(directory, local, sort);
+
+    std::vector<fs::path> expected;
+    for (const auto& file : filenames)
+    {
+        expected.push_back(directory / file);
+    }
+
+    BOOST_CHECK_EQUAL_COLLECTIONS(entries.begin(), entries.end(), expected.begin(), expected.end());
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()