diff --git a/src/test/perl/RecursiveCopy.pm b/src/test/perl/RecursiveCopy.pm
index 28ecaf6db2..54459dd401 100644
--- a/src/test/perl/RecursiveCopy.pm
+++ b/src/test/perl/RecursiveCopy.pm
@@ -31,10 +31,12 @@ use File::Copy;
 Recursively copy all files and directories from $from to $to.
 
 Only regular files and subdirectories are copied.  Trying to copy other types
-of directory entries raises an exception.
+of directory entries results in skipping those. While it would be tempting to
+raise an error, it could be possible that a file or a directory is suddendly
+removed while being copied or scanned.
 
-Raises an exception if a file would be overwritten, the source directory can't
-be read, or any I/O operation fails. Always returns true.
+Raises an exception if a file would be overwritten or any I/O operation fails,
+except if on ENOENT which is considered as a no-op. Always returns true.
 
 If the B<filterfn> parameter is given, it must be a subroutine reference.
 This subroutine will be called for each entry in the source directory with its
@@ -91,10 +93,9 @@ sub _copypath_recurse
 	# Check for symlink -- needed only on source dir
 	die "Cannot operate on symlinks" if -l $srcpath;
 
-	# Can't handle symlinks or other weird things
-	die "Source path \"$srcpath\" is not a regular file or directory"
-	  unless -f $srcpath
-		  or -d $srcpath;
+	# Can't handle symlinks or other weird things. A missing file or
+	# directory is also a no-op.
+	return 1 unless -f $srcpath or -d $srcpath;
 
 	# Abort if destination path already exists.  Should we allow directories
 	# to exist already?
@@ -104,15 +105,41 @@ sub _copypath_recurse
 	# same name and we're done.
 	if (-f $srcpath)
 	{
-		copy($srcpath, $destpath)
-		  or die "copy $srcpath -> $destpath failed: $!";
+		unless (copy($srcpath, $destpath))
+		{
+			# Ignore ENOENT to prevent problems where the file whose copy
+			# is attempted gets suddendly removed.
+			if ($!{ENOENT})
+			{
+				warn "copy $srcpath -> $destpath failed: $!";
+			}
+			else
+			{
+				die "copy $srcpath -> $destpath failed: $!";
+			}
+		}
 		return 1;
 	}
 
 	# Otherwise this is directory: create it on dest and recurse onto it.
 	mkdir($destpath) or die "mkdir($destpath) failed: $!";
 
-	opendir(my $directory, $srcpath) or die "could not opendir($srcpath): $!";
+	my $directory;
+	unless (opendir($directory, $srcpath))
+	{
+		# Ignore ENOENT to prevent problems where the directory whose
+		# scan is done gets suddendly removed.
+		if ($!{ENOENT})
+		{
+			warn "could not opendir($srcpath): $!";
+			return 1;
+		}
+		else
+		{
+			die "could not opendir($srcpath): $!";
+		}
+	}
+
 	while (my $entry = readdir($directory))
 	{
 		next if ($entry eq '.' or $entry eq '..');
diff --git a/src/test/recovery/t/010_logical_decoding_timelines.pl b/src/test/recovery/t/010_logical_decoding_timelines.pl
index edc0219c9c..5620450acf 100644
--- a/src/test/recovery/t/010_logical_decoding_timelines.pl
+++ b/src/test/recovery/t/010_logical_decoding_timelines.pl
@@ -24,7 +24,6 @@ use warnings;
 use PostgresNode;
 use TestLib;
 use Test::More tests => 13;
-use RecursiveCopy;
 use File::Copy;
 use IPC::Run ();
 use Scalar::Util qw(blessed);
