Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure: how to execute shell commands with piping?

I found (use '[clojure.java.shell :only [sh]]) for executing shell commands with clojure. Now, while (sh "ls" "-a") does the job, (sh "ls" "-a" "| grep" "Doc") doesn't. What's the trick?

like image 793
shakedzy Avatar asked Apr 20 '16 09:04

shakedzy


1 Answers

clojure.java.shell/sh executes a command (the first argument passed to sh function) with specified arguments (the rest of the parameters passed to sh).

When you execute:

(sh "ls" "-a" "| grep" "Doc")

you ask to execute ls with parameters -a, | grep and Doc.

When you type ls -a | grep Doc in your terminal then the shell interprets it as executing ls, taking its std out and pass it as std in to another process (grep) that should be started by the shell.

You could simulate what the shell is doing by starting ls as one process, take its std output and then execute grep passing output from ls as its input.

The simpler solution would be to just ask a shell process to execute everything as if it was typed in terminal:

(sh "bash" "-c" "ls -a | grep Doc")

It's important to pass -c and ls ... as separate arguments so bash gets them as a separate parameters. You also need to have the whole command you want to execute as one string (ls -a | grep Doc). Otherwise only the first argument after -c will be treated as a command. For example this won't do what you would like:

(sh "bash" "-c" "ls -a" "|" "grep Doc")

like image 60
Piotrek Bzdyl Avatar answered Oct 06 '22 19:10

Piotrek Bzdyl