diff --git a/src/lib.rs b/src/lib.rs
index 9a7ccda..b91174e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -720,6 +720,16 @@ impl Drop for PushEnv<'_> {
     }
 }
 
+/// The output of a finished process for specific stream. Another stream will be printed to the corresponds system stream
+#[derive(Debug)]
+pub struct StreamOutput {
+    /// The status (exit code) of the process.
+    pub exit_status: ExitStatus,
+    /// The data that the process wrote to stdout or stderr.
+    /// Any trailing newline or carriage return will be trimmed.
+    pub stream_output: String,
+}
+
 /// A builder object for constructing a subprocess.
 ///
 /// A [`Cmd`] is usually created with the [`cmd!`] macro. The command exists
@@ -968,21 +978,33 @@ impl<'a> Cmd<'a> {
 
     /// Run the command and return its stdout as a string. Any trailing newline or carriage return will be trimmed.
     pub fn read(&self) -> Result<String> {
-        self.read_stream(false)
+        Ok(self.read_stream(false)?.stream_output)
     }
 
-    /// Run the command and return its stderr as a string. Any trailing newline or carriage return will be trimmed.
+    /// Run the command and return its stderr as a string.
     pub fn read_stderr(&self) -> Result<String> {
+        Ok(self.read_stream(true)?.stream_output)
+    }
+
+    /// Run the command and return its stderr as a string and exit status.
+    /// Any trailing newline or carriage return will be trimmed.
+    pub fn read_stderr_output(&self) -> Result<StreamOutput> {
         self.read_stream(true)
     }
 
+    /// Run the command and return its stdout as a string and exit status.
+    /// Any trailing newline or carriage return will be trimmed.
+    pub fn read_stdout_output(&self) -> Result<StreamOutput> {
+        self.read_stream(false)
+    }
+
     /// Run the command and return its output.
     pub fn output(&self) -> Result<Output> {
         self.output_impl(true, true)
     }
     // endregion:running
 
-    fn read_stream(&self, read_stderr: bool) -> Result<String> {
+    fn read_stream(&self, read_stderr: bool) -> Result<StreamOutput> {
         let read_stdout = !read_stderr;
         let output = self.output_impl(read_stdout, read_stderr)?;
         self.check_status(output.status)?;
@@ -997,7 +1019,7 @@ impl<'a> Cmd<'a> {
             stream.pop();
         }
 
-        Ok(stream)
+        Ok(StreamOutput { exit_status: output.status, stream_output: stream })
     }
 
     fn output_impl(&self, read_stdout: bool, read_stderr: bool) -> Result<Output> {
diff --git a/tests/it/main.rs b/tests/it/main.rs
index 3214840..e4d0f3d 100644
--- a/tests/it/main.rs
+++ b/tests/it/main.rs
@@ -54,6 +54,21 @@ fn multiline() {
     assert_eq!(output, "hello");
 }
 
+#[test]
+fn read_with_exit_status() {
+    let sh = setup();
+    let output = cmd!(
+        sh,
+        "
+        xecho hello
+        "
+    )
+    .read_stdout_output()
+    .unwrap();
+    assert_eq!(output.stream_output, "hello");
+    assert!(output.exit_status.success());
+}
+
 #[test]
 fn interpolation() {
     let sh = setup();
@@ -185,6 +200,15 @@ fn read_stderr() {
     assert!(output.contains("snafu"));
 }
 
+#[test]
+fn read_stderr_with_exit_code() {
+    let sh = setup();
+
+    let output = cmd!(sh, "xecho -f -e snafu").ignore_status().read_stderr_output().unwrap();
+    assert!(output.stream_output.contains("snafu"));
+    assert!(!output.exit_status.success())
+}
+
 #[test]
 fn unknown_command() {
     let sh = setup();