diff --git a/apps/fsearch/fsearch.cpp b/apps/fsearch/fsearch.cpp
index 2093ca6dd485c0f81ec4da34e5db7d0c259846b6..0c4de308c8dfc62f8ca41769573ac77ad026a3d5 100644
--- a/apps/fsearch/fsearch.cpp
+++ b/apps/fsearch/fsearch.cpp
@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: LGPL-3.0-or-later
 // Copyright © 2021-2022 Florian Fischer, Florian Schmaus
 #include <fcntl.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 #include <array>
+#include <atomic>
 #include <boost/program_options.hpp>
 #include <climits>
 #include <cstdlib>
@@ -26,13 +28,30 @@ namespace po = boost::program_options;
 
 #define EMPER_RIPGREP_BUFSIZE 4096
 
-const char* needle;
-size_t needle_len;
+static const char* needle;
+static size_t needle_len;
 
-emper::Semaphore* max_running;
+static emper::Semaphore* max_running;
+
+static bool stdoutNeedsOffset = false;
+static std::atomic<off_t> stdoutOffset = 0;
 
 static enum emper::StealingMode stealingMode;
 
+static void writeFoundPath(const std::string& path) {
+	std::array<char, PATH_MAX + 1> outBuf;
+	memcpy(outBuf.data(), path.c_str(), path.length());
+	outBuf[path.length()] = '\n';
+
+	const size_t outLen = path.length() + 1;
+
+	off_t offset = -1;
+	if (stdoutNeedsOffset)
+		offset = stdoutOffset.fetch_add(static_cast<off_t>(outLen), std::memory_order_relaxed);
+
+	emper::io::writeFileAndWait(STDOUT_FILENO, outBuf.data(), outLen, offset);
+}
+
 void search(const std::string& path) {
 	if (max_running) {
 		max_running->acquire();
@@ -48,10 +67,7 @@ void search(const std::string& path) {
 	ssize_t bytes_read = emper::io::readFileAndWait(fd, buf.data(), buf.size(), 0);
 	while (bytes_read > 0) {
 		if (memmem(&buf[0], bytes_read, needle, needle_len)) {
-			std::array<char, PATH_MAX + 1> outBuf;
-			memcpy(outBuf.data(), path.c_str(), path.length());
-			outBuf[path.length()] = '\n';
-			emper::io::writeFileAndWait(STDOUT_FILENO, outBuf.data(), path.length() + 1, -1);
+			writeFoundPath(path);
 			goto out;
 		}
 
@@ -105,6 +121,12 @@ static auto fssearch(const po::variables_map& vm) -> int {
 
 	Runtime runtime;
 
+	struct stat statBuf;
+	int res = fstat(STDOUT_FILENO, &statBuf);
+	if (res) DIE_MSG_ERRNO("fstat(STDOUT_FILENO) failed");
+
+	stdoutNeedsOffset = S_ISREG(statBuf.st_mode);
+
 	std::cerr << "Starting fsearch with stealingMode=" << stealingMode;
 	if (max_running) std::cerr << " and " << max_running->getCount() << " file fibers";
 	std::cerr << std::endl;