diff --git a/crates/nu-command/src/commands/which_.rs b/crates/nu-command/src/commands/which_.rs
index 76d5a471ee..0472901650 100644
--- a/crates/nu-command/src/commands/which_.rs
+++ b/crates/nu-command/src/commands/which_.rs
@@ -17,6 +17,7 @@ impl WholeStreamCommand for Which {
     fn signature(&self) -> Signature {
         Signature::build("which")
             .required("application", SyntaxShape::String, "application")
+            .rest(SyntaxShape::String, "additional applications")
             .switch("all", "list all executables", Some('a'))
     }
 
@@ -166,56 +167,76 @@ async fn get_all_entries_in_path(_: &str, _: Tag) -> Vec<Value> {
 #[derive(Deserialize, Debug)]
 struct WhichArgs {
     application: Tagged<String>,
+    rest: Vec<Tagged<String>>,
     all: bool,
 }
 
-async fn which(args: CommandArgs) -> Result<OutputStream, ShellError> {
-    let scope = args.scope.clone();
-
-    let (WhichArgs { application, all }, _) = args.process().await?;
-
+async fn which_single(application: Tagged<String>, all: bool, scope: &Scope) -> Vec<Value> {
     let (external, prog_name) = if application.starts_with('^') {
         (true, application.item[1..].to_string())
     } else {
         (false, application.item.clone())
     };
 
-    let mut output = vec![];
-
     //If prog_name is an external command, don't search for nu-specific programs
     //If all is false, we can save some time by only searching for the first matching
     //program
     //This match handles all different cases
     match (all, external) {
         (true, true) => {
-            output.extend(get_all_entries_in_path(&prog_name, application.tag.clone()).await);
+            return get_all_entries_in_path(&prog_name, application.tag.clone()).await;
         }
         (true, false) => {
+            let mut output: Vec<Value> = vec![];
             output.extend(get_entries_in_nu(
-                &scope,
+                scope,
                 &prog_name,
                 application.tag.clone(),
                 false,
             ));
             output.extend(get_all_entries_in_path(&prog_name, application.tag.clone()).await);
+            return output;
         }
         (false, true) => {
             if let Some(entry) = get_first_entry_in_path(&prog_name, application.tag.clone()).await
             {
-                output.push(entry);
+                return vec![entry];
             }
+            return vec![];
         }
         (false, false) => {
-            let nu_entries = get_entries_in_nu(&scope, &prog_name, application.tag.clone(), true);
+            let nu_entries = get_entries_in_nu(scope, &prog_name, application.tag.clone(), true);
             if !nu_entries.is_empty() {
-                output.push(nu_entries[0].clone());
+                return vec![nu_entries[0].clone()];
             } else if let Some(entry) =
                 get_first_entry_in_path(&prog_name, application.tag.clone()).await
             {
-                output.push(entry);
+                return vec![entry];
             }
+            return vec![];
         }
     }
+}
+
+async fn which(args: CommandArgs) -> Result<OutputStream, ShellError> {
+    let scope = args.scope.clone();
+
+    let (
+        WhichArgs {
+            application,
+            rest,
+            all,
+        },
+        _,
+    ) = args.process().await?;
+
+    let mut output = vec![];
+
+    for app in vec![application].into_iter().chain(rest.into_iter()) {
+        let values = which_single(app, all, &scope).await;
+        output.extend(values);
+    }
+
     Ok(futures::stream::iter(output.into_iter().map(ReturnSuccess::value)).to_output_stream())
 }