diff --git a/configure b/configure
index 938668e996b10b5f380655d3b9383205ad1630f6..b47897c65b20b124bb8da15f3830993411bb6a14 100755
--- a/configure
+++ b/configure
@@ -701,6 +701,7 @@ enable_matheval
 enable_zlib
 enable_clock_gettime
 enable_gettimeofday
+enable_readdir_r
 enable_cregex
 enable_dlopen
 enable_execinfo
@@ -1350,6 +1351,8 @@ Optional Features:
   --enable-zlib           enable search for zlib, default: yes
   --enable-clock-gettime  enable search for gettime, default: yes
   --enable-gettimeofday   enable search for gettimeofday, default: yes
+  --enable-readdir-r      enable search for readdir_r (threadsafe), default:
+                          yes
   --enable-cregex         enable search for C regular expression, default: yes
   --enable-dlopen         enable search for dlopen, default: yes
   --enable-execinfo       enable search for execinfo, default: yes
@@ -2525,6 +2528,24 @@ fi
 
 
 
+readdir_r=
+# Check whether --enable-readdir-r was given.
+if test "${enable_readdir_r+set}" = set; then :
+  enableval=$enable_readdir_r; case "${enableval}" in
+             (yes) readdir_r=true ;;
+             (no)  readdir_r=false ;;
+             (*)   as_fn_error $? "wrong argument to --enable-readdir-r" "$LINENO" 5 ;;
+  esac
+else
+  case "yes" in
+             (yes) readdir_r=true ;;
+             (no)  readdir_r=false ;;
+  esac
+
+fi
+
+
+
 cregex=
 # Check whether --enable-cregex was given.
 if test "${enable_cregex+set}" = set; then :
@@ -5634,6 +5655,30 @@ fi
 $as_echo "$as_me: WARNING: cannot enable __PLUMED_HAS_GETTIMEOFDAY" >&2;}
     fi
 
+fi
+if test $readdir_r == true ; then
+
+    found=ko
+    ac_fn_cxx_check_header_mongrel "$LINENO" "dirent.h" "ac_cv_header_dirent_h" "$ac_includes_default"
+if test "x$ac_cv_header_dirent_h" = xyes; then :
+
+      ac_fn_cxx_check_func "$LINENO" "readdir_r" "ac_cv_func_readdir_r"
+if test "x$ac_cv_func_readdir_r" = xyes; then :
+  found=ok
+fi
+
+
+fi
+
+
+    if test $found == ok ; then
+      $as_echo "#define __PLUMED_READDIR_R 1" >>confdefs.h
+
+    else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot enable __PLUMED_READDIR_R" >&5
+$as_echo "$as_me: WARNING: cannot enable __PLUMED_READDIR_R" >&2;}
+    fi
+
 fi
 if test $cregex == true ; then
 
diff --git a/configure.ac b/configure.ac
index 16b8074843076ed106bcfcdfc780be6a13f02b01..c71f67b5e18ce98fbad7dc157a46ce2c751367b0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -98,6 +98,7 @@ PLUMED_CONFIG_ENABLE([matheval],[matheval],[search for matheval],[yes])
 PLUMED_CONFIG_ENABLE([zlib],[zlib],[search for zlib],[yes])
 PLUMED_CONFIG_ENABLE([clock_gettime],[clock-gettime],[search for gettime],[yes])
 PLUMED_CONFIG_ENABLE([gettimeofday],[gettimeofday],[search for gettimeofday],[yes])
+PLUMED_CONFIG_ENABLE([readdir_r],[readdir-r],[search for readdir_r (threadsafe)],[yes])
 PLUMED_CONFIG_ENABLE([cregex],[cregex],[search for C regular expression],[yes])
 PLUMED_CONFIG_ENABLE([dlopen],[dlopen],[search for dlopen],[yes])
 PLUMED_CONFIG_ENABLE([execinfo],[execinfo],[search for execinfo],[yes])
@@ -294,6 +295,9 @@ fi
 if test $gettimeofday == true ; then
   PLUMED_CHECK_PACKAGE([sys/time.h], [gettimeofday], [__PLUMED_HAS_GETTIMEOFDAY])
 fi
+if test $readdir_r == true ; then
+  PLUMED_CHECK_PACKAGE([dirent.h],[readdir_r],[__PLUMED_READDIR_R])
+fi
 if test $cregex == true ; then
   PLUMED_CHECK_PACKAGE([regex.h],[regcomp],[__PLUMED_HAS_CREGEX])
 fi
diff --git a/src/tools/Tools.cpp b/src/tools/Tools.cpp
index 52fb5d9f149f724df30271a882147f32f5ab9b92..fed7ddfa8d2a85099b467a29939150db09f20f49 100644
--- a/src/tools/Tools.cpp
+++ b/src/tools/Tools.cpp
@@ -280,8 +280,23 @@ vector<string> Tools::ls(const string&d){
   DIR*dir;
   vector<string> result;
   if ((dir=opendir(d.c_str()))){
-    struct dirent *ent;
-    while ((ent = readdir (dir))) if(string(ent->d_name)!="." && string(ent->d_name)!="..") result.push_back(ent->d_name);
+    struct dirent *res;
+    struct dirent ent;
+    while(true){
+#if defined(__PLUMED_READDIR_R)
+      readdir_r(dir,&ent,&res);
+#else
+// cppcheck complains about this:
+// (portability) Non reentrant function 'readdir' called. For threadsafe applications it is recommended to use the reentrant replacement function 'readdir_r'.
+// since we use it only if readdir_r is not available, I suppress the warning
+// GB
+// cppcheck-suppress nonreentrantFunctionsreaddir
+      res=readdir(dir);
+      (void) ent; // avoid warning
+#endif
+      if(!res) break;
+      if(string(res->d_name)!="." && string(res->d_name)!="..") result.push_back(res->d_name);
+    }
     closedir (dir);
   }
   return result;