diff --git a/README.md b/README.md
index f84d325f819e8afeaf7eec173ad53934acac914b..7a42cd1295583742800957e037cdd13f6009b14c 100644
--- a/README.md
+++ b/README.md
@@ -98,7 +98,7 @@ command arg1 arg2 arg3; command arg1 arg2 arg3; command arg1 arg2 arg3
 
 ### Piping & Redirecting Standard Output
 
-The pipe (`|`) and redirect (`>`) operators are used for manipulating the standard output. 
+The pipe (`|`) and redirect (`>`) operators are used for manipulating the standard output.
 
 ```ion
 command arg1 | other_command | another_command arg2
@@ -110,7 +110,7 @@ command arg1 > file
 The `^|` and `^>` operators are used for manipulating the standard error.
 
 ```ion
-command arg1 ^| other_command # Not supported yet
+command arg1 ^| other_command
 command arg1 ^> file
 ```
 
diff --git a/src/parser/pipelines.rs b/src/parser/pipelines.rs
index b324f1d27b0398c418ff0235a158c7d1516a71e3..6efc69d061f6855cf8b51448ee2f77abf110e524 100644
--- a/src/parser/pipelines.rs
+++ b/src/parser/pipelines.rs
@@ -23,12 +23,16 @@ const IS_VALID: u8 = 255 ^ (BACKSLASH + WHITESPACE);
 #[derive(PartialEq)]
 enum RedirMode { False, Stdin, Stdout(RedirectFrom), StdoutAppend(RedirectFrom) }
 
+/// Determine which type of job will be selected based on the next character.
+///
+/// - If the `|` char was found and the next character is `|`, it's `Or`
+/// - If the `&` char was found and the next character is `&`, it's `And`
 fn get_job_kind(args: &str, index: usize, pipe_char_was_found: bool) -> (JobKind, bool) {
     if pipe_char_was_found {
         if args.bytes().nth(index) == Some(b'|') {
             (JobKind::Or, true)
         } else {
-            (JobKind::Pipe, false)
+            (JobKind::Pipe(RedirectFrom::Stdout), false)
         }
     } else if args.bytes().nth(index) == Some(b'&') {
         (JobKind::And, true)
@@ -74,12 +78,16 @@ pub fn collect(pipelines: &mut Vec<Pipeline>, possible_error: &mut Option<&str>,
         }
 
         macro_rules! job_found {
-            ($pipe_char_was_found:expr) => {{
-                // Determine which type of job will be selected based on the next character.
-                //
-                // - If the `|` char was found and the next character is `|`, it's `Or`
-                // - If the `&` char was found and the next character is `&`, it's `And`
-                let (kind, advance) = get_job_kind(args, index+1, $pipe_char_was_found);
+            ($from:expr, $pipe_char_was_found:expr) => {{
+
+                let (kind, advance) = match $from {
+                    RedirectFrom::Stdout => get_job_kind(args, index+1, $pipe_char_was_found),
+                    _ => {
+                        arg_start += 1;
+                        index += 1;
+                        (JobKind::Pipe($from), true)
+                    }
+                };
 
                 // If either `And` or `Or` was found, advance the iterator once.
                 if advance { let _ = args_iter.next(); }
@@ -87,13 +95,14 @@ pub fn collect(pipelines: &mut Vec<Pipeline>, possible_error: &mut Option<&str>,
                 if arguments.is_empty() {
                     jobs.push(Job::new(vec![args[arg_start..index].to_owned()], kind));
                 } else {
-                    if args.as_bytes()[index-1] != b' ' {
+                    let byte_index = if $from == RedirectFrom::Stdout { index-1 } else { index-2 };
+                    if args.as_bytes()[byte_index] != b' ' {
                         arguments.push(args[arg_start..index].to_owned());
                     }
                     jobs.push(Job::new(arguments.clone(), kind));
                     arguments.clear();
                 }
-                if advance {  index += 1; }
+                if advance { index += 1; }
                 arg_start = index + 1;
             }}
         }
@@ -124,19 +133,27 @@ pub fn collect(pipelines: &mut Vec<Pipeline>, possible_error: &mut Option<&str>,
                                 arg_start += 1;
                             }
                         },
-                        b'|' if (flags & (255 ^ BACKSLASH) == 0) => job_found!(true),
+                        b'|' if (flags & (255 ^ BACKSLASH) == 0) => job_found!(RedirectFrom::Stdout, true),
                         b'&' if (flags & (255 ^ BACKSLASH) == 0) => {
-                            if args_iter.peek() == Some(&b'>') {
-                                let _ = args_iter.next();
-                                redir_found!(RedirMode::Stdout(RedirectFrom::Both));
-                            } else {
-                                job_found!(false)
+                            match args_iter.peek() {
+                                Some(&b'>') => {
+                                    let _ = args_iter.next();
+                                    redir_found!(RedirMode::Stdout(RedirectFrom::Both));
+                                },
+                                _ => job_found!(RedirectFrom::Stdout, false)
                             }
                         },
                         b'^' if (flags & IS_VALID == 0) => {
-                            if args_iter.peek() == Some(&b'>') {
-                                let _ = args_iter.next();
-                                redir_found!(RedirMode::Stdout(RedirectFrom::Stderr));
+                            match args_iter.peek() {
+                                Some(&b'>') => {
+                                    let _ = args_iter.next();
+                                    redir_found!(RedirMode::Stdout(RedirectFrom::Stderr));
+                                },
+                                Some(&b'|') => {
+                                    let _ = args_iter.next();
+                                    job_found!(RedirectFrom::Stderr, true);
+                                }
+                                _ => ()
                             }
                         },
                         b'>' if (flags & IS_VALID == 0) => redir_found!(RedirMode::Stdout(RedirectFrom::Stdout)),
diff --git a/src/pipe.rs b/src/pipe.rs
index cab157f02a15427c9ee4ba63190a65669d1cb271..aee2e932bdc177ab6df53edc31c7569704aabf0c 100644
--- a/src/pipe.rs
+++ b/src/pipe.rs
@@ -101,7 +101,12 @@ pub fn pipe(commands: &mut [(Command, JobKind)]) -> i32 {
                 let mut children: Vec<Option<Child>> = Vec::new();
 
                 // Initialize the first job
-                command.stdout(Stdio::piped());
+                let _ = match from {
+                    RedirectFrom::Both => command.stderr(Stdio::piped()), // TODO: Fix this
+                    RedirectFrom::Stderr => command.stderr(Stdio::piped()),
+                    RedirectFrom::Stdout => command.stdout(Stdio::piped()),
+                };
+
                 let child = command.spawn().ok();
                 if child.is_none() {
                     let stderr = io::stderr();
@@ -112,12 +117,18 @@ pub fn pipe(commands: &mut [(Command, JobKind)]) -> i32 {
 
                 // Append other jobs until all piped jobs are running.
                 while let Some(&mut (ref mut command, kind)) = commands.next() {
-                    if let JobKind::Pipe(_) = kind { command.stdout(Stdio::piped()); }
+                    if let JobKind::Pipe(from) = kind {
+                        let _ = match from {
+                            RedirectFrom::Both => command.stderr(Stdio::piped()), // TODO: Fix this
+                            RedirectFrom::Stderr => command.stderr(Stdio::piped()),
+                            RedirectFrom::Stdout => command.stdout(Stdio::piped()),
+                        };
+                    }
                     if let Some(spawned) = children.last() {
                         if let Some(ref child) = *spawned {
                             unsafe {
                                 match from {
-                                    // Find a way to properly implement this.
+                                    // TODO: Find a way to properly implement this.
                                     RedirectFrom::Both => if let Some(ref stderr) = child.stderr {
                                         command.stdin(Stdio::from_raw_fd(stderr.as_raw_fd()));
                                     },