16

Perl and PHP do this with backticks. For example,

$output = `ls`;

Returns a directory listing. A similar function, system("foo"), returns the operating system return code for the given command foo. I'm talking about a variant that returns whatever foo prints to stdout.

How do other languages do this? Is there a canonical name for this function? (I'm going with "backtick"; though maybe I could coin "syslurp".)

Peter O.
  • 32,158
  • 14
  • 82
  • 96
dreeves
  • 26,430
  • 45
  • 154
  • 229
  • Code-challenge set and answered for a system shell 'ls' in Java (in a platform independent way), see below (reference to a DZones Java Snippets code page) – VonC Oct 26 '08 at 01:09
  • 1
    The canonical name is [command substitution](http://en.wikipedia.org/wiki/Command_substitution). – Brent Bradburn Oct 22 '12 at 18:09

27 Answers27

20

Python

from subprocess import check_output as qx

output = qx(['ls', '-lt'])

Python <2.7 or <3.1

Extract subprocess.check_output() from subprocess.py or adapt something similar to:

import subprocess

def cmd_output(args, **kwds):
  kwds.setdefault("stdout", subprocess.PIPE)
  kwds.setdefault("stderr", subprocess.STDOUT)
  p = subprocess.Popen(args, **kwds)
  return p.communicate()[0]

print cmd_output("ls -lt".split())

The subprocess module has been in the stdlib since 2.4.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
12

Python:

import os
output = os.popen("foo").read()
dreeves
  • 26,430
  • 45
  • 154
  • 229
9

[At the request of Alexman and dreeves -- see comments --, you will find at this DZones Java Snippet page a full version Os-independent for making, in this instance, a 'ls'. This is a direct answer to their code-challenge.
What follows below is just the core: Runtime.exec, plus 2 thread to listen to stdout and stderr. ]

Java "Simple!":

E:\classes\com\javaworld\jpitfalls\article2>java GoodWindowsExec "dir *.java"
Executing cmd.exe /C dir *.java
...

Or in java code

String output = GoodWindowsExec.execute("dir");

But to do that, you need to code...
... this is embarrassing.

import java.util.*;
import java.io.*;
class StreamGobbler extends Thread
{
    InputStream is;
    String type;
    StringBuffer output = new StringBuffer();

    StreamGobbler(InputStream is, String type)
    {
        this.is = is;
        this.type = type;
    }

    public void run()
    {
        try
        {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null)
                System.out.println(type + ">" + line);
                output.append(line+"\r\n")
            } catch (IOException ioe)
              {
                ioe.printStackTrace();  
              }
    }
    public String getOutput()
    {
        return this.output.toString();
    }
}
public class GoodWindowsExec
{
    public static void main(String args[])
    {
        if (args.length < 1)
        {
            System.out.println("USAGE: java GoodWindowsExec <cmd>");
            System.exit(1);
        }
    }
    public static String execute(String aCommand)
    {
        String output = "";
        try
        {            
            String osName = System.getProperty("os.name" );
            String[] cmd = new String[3];
            if( osName.equals( "Windows 95" ) )
            {
                cmd[0] = "command.com" ;
                cmd[1] = "/C" ;
                cmd[2] = aCommand;
            }
            else if( osName.startsWith( "Windows" ) )
            {
                cmd[0] = "cmd.exe" ;
                cmd[1] = "/C" ;
                cmd[2] = aCommand;
            }

            Runtime rt = Runtime.getRuntime();
            System.out.println("Executing " + cmd[0] + " " + cmd[1] 
                               + " " + cmd[2]);
            Process proc = rt.exec(cmd);
            // any error message?
            StreamGobbler errorGobbler = new 
                StreamGobbler(proc.getErrorStream(), "ERROR");            

            // any output?
            StreamGobbler outputGobbler = new 
                StreamGobbler(proc.getInputStream(), "OUTPUT");

            // kick them off
            errorGobbler.start();
            outputGobbler.start();

            // any error???
            int exitVal = proc.waitFor();
            System.out.println("ExitValue: " + exitVal);   

            output = outputGobbler.getOutput();
            System.out.println("Final output: " + output);   

        } catch (Throwable t)
          {
            t.printStackTrace();
          }
        return output;
    }
}
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • can you get rid of the command line stuff and show how to get the output into a string in the java code itself? – dreeves Oct 25 '08 at 20:00
  • 1
    Done: String output = GoodWindowsExec.execute("dir"); – VonC Oct 25 '08 at 20:19
  • 2
    Where's the AbstractFactoryBuilderFactory.buildExecFactory() call? – Axeman Oct 25 '08 at 22:33
  • Right here, Sir, right here: http://books.google.fr/books?id=M_eLGmh7dGwC&pg=PA35&lpg=PA35&dq=java+AbstractFactory+BuilderFactory&source=web&ots=jskxqzgb9a&sig=o1mlZCtTn-6dZhrdDowV-qtDwhw&hl=fr&sa=X&oi=book_result&resnum=3&ct=result#PPA37,M1 – VonC Oct 25 '08 at 22:54
  • ok, but seriously, how would you do this in java? :) also, is the above windows-specific? is there an os-independent way to do this? – dreeves Oct 25 '08 at 23:09
  • Riight... working on it now. The above is indeed windows-specific. I will post on http://snippets.dzone.com/tag/java a full generic example of what it would take to make a simple 'ls' (or dir for Windows) in Java. – VonC Oct 25 '08 at 23:15
  • I think that whole StreamGobbler thing is an overkill. And yes, it is OS specific because backticks are OS specific too. Having said that, it can easily be ported to unix. The command you need is called "/bin/sh" and the first argument is "-c". – Leon Timmermans Oct 25 '08 at 23:16
  • Yes, but it is not nearly as fun than to pile up another "overkill" layer on top on the first one and goes full design pattern ;-) – VonC Oct 25 '08 at 23:23
  • And StreamGobbler is not exactly overkill, but the surest way to monitor what is going on with the output of your function. If its execution time is quite long, you will be glad to have StreamGobbler to report it (in a log file for instance) – VonC Oct 25 '08 at 23:24
  • StreamGobbler is totally necessary if the command is writing to both stdout and stderr. If there's nothing to read stderr, there's a good chance the spawned process will block leading to deadlock. Half the time I spawn new processes in Java I forget and get bitten by this. – Dave Ray Dec 02 '08 at 20:04
  • 1
    "Java. The most verbose language known to man." -- wrong, but can be corrected. "Java. The most verbose language invented by man." That works because Cobol was invented by woman. – Windows programmer Dec 16 '08 at 23:12
  • @Windowsprogrammer What about assembler? – Display Name Dec 07 '13 at 20:04
8

Yet another way to do it in Perl (TIMTOWTDI)

$output = <<`END`;
ls
END

This is specially useful when embedding a relatively large shell script in a Perl program

Leon Timmermans
  • 30,029
  • 2
  • 61
  • 110
7

Ruby: either backticks or the '%x' builtin syntax.

puts `ls`;
puts %x{ls};
Ovid
  • 11,580
  • 9
  • 46
  • 76
7

An alternative method in perl

$output = qx/ls/;

This had the advantage that you can choose your delimiters, making it possible to use ` in the command (though IMHO you should reconsider your design if you really need to do that). Another important advantage is that if you use single quotes as delimiter, variables will not be interpolated (a very useful)

Leon Timmermans
  • 30,029
  • 2
  • 61
  • 110
7

Haskell:

import Control.Exception
import System.IO
import System.Process
main = bracket (runInteractiveCommand "ls") close $ \(_, hOut, _, _) -> do
    output <- hGetContents hOut
    putStr output
  where close (hIn, hOut, hErr, pid) =
          mapM_ hClose [hIn, hOut, hErr] >> waitForProcess pid

With MissingH installed:

import System.Cmd.Utils
main = do
    (pid, output) <- pipeFrom "ls" []
    putStr output
    forceSuccess pid

This is an easy operation in "glue" languages like Perl and Ruby, but Haskell isn't.

ephemient
  • 198,619
  • 38
  • 280
  • 391
6

In shell

OUTPUT=`ls`

or alternatively

OUTPUT=$(ls)

This second method is better because it allows nesting, but isn't supported by all shells, unlike the first method.

Leon Timmermans
  • 30,029
  • 2
  • 61
  • 110
6

Erlang:

os:cmd("ls")
JesperE
  • 63,317
  • 21
  • 138
  • 197
6

Well, since this is system dependent, there are many languages that do not have a built-in wrapper for the various system calls needed.

For example, Common Lisp itself was not designed to run on any specific system. SBCL (the Steel Banks Common Lisp implementation), though, does provide an extension for Unix-like systems, as do most other CL implementations. This is much more "mighty" than just getting the output, of course (you have control over the running process, can specify all kinds of stream directions, etc., confer to the SBCL manual, chapter 6.3), but it is easy to write a little macro for this specific purpose:

(defmacro with-input-from-command ((stream-name command args) &body body)
  "Binds the output stream of command to stream-name, then executes the body
   in an implicit progn."
  `(with-open-stream
       (,stream-name
         (sb-ext:process-output (sb-ext:run-program ,command
                                                    ,args
                                                    :search t
                                                    :output :stream)))
     ,@body))

Now, you can use it like this:

(with-input-from-command (ls "ls" '("-l"))
  ;;do fancy stuff with the ls stream
  )

Perhaps you want to slurp it all into one string. The macro is trivial (though perhaps more concise code is possible):

(defmacro syslurp (command args)
  "Returns the output from command as a string. command is to be supplied
   as string, args as a list of strings."
  (let ((istream (gensym))
        (ostream (gensym))
        (line (gensym)))
    `(with-input-from-command (,istream ,command ,args)
       (with-output-to-string (,ostream)
         (loop (let ((,line (read-line ,istream nil)))
                 (when (null ,line) (return))
                 (write-line ,line ,ostream)))))))

Now you can get a string with this call:

(syslurp "ls" '("-l"))
Svante
  • 50,694
  • 11
  • 78
  • 122
  • 1
    Thanks! Very handy! This seems to me both illustrative of lisp's power that it's so easy to build this from scratch from very general tools (compare to the abomination that is java!), but also illustrative of lisp's primary problem: that things like syslurp aren't prepackaged in standard libraries. – dreeves Dec 13 '08 at 21:37
  • 2
    Oh, there are many libraries. Some regarding system interaction are listed at http://www.cliki.net/compatibility%20layers – Svante Dec 13 '08 at 22:26
4

Mathematica:

output = Import["!foo", "Text"];
dreeves
  • 26,430
  • 45
  • 154
  • 229
4

Yet another way (or 2!) in Perl....

open my $pipe, 'ps |';
my @output = < $pipe >;
say @output;

open can also be written like so...

open my $pipe, '-|', 'ps'
AndyG
  • 39,700
  • 8
  • 109
  • 143
draegtun
  • 22,441
  • 5
  • 48
  • 71
  • I was thinking of that one too, but I don't think the "various languages" part of this thread is getting done. – Axeman Oct 25 '08 at 22:31
4

Years ago I wrote a plugin for jEdit that interfaced to a native application. This is what I used to get the streams off the running executable. Only thing left to do is while((String s = stdout.readLine())!=null){...}:

/* File:    IOControl.java
 *
 * created: 10 July 2003
 * author:  dsm
 */
package org.jpop.io;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;

/**
 *  Controls the I/O for a process. When using the std[in|out|err] streams, they must all be put on
 *  different threads to avoid blocking!
 *
 * @author     dsm
 * @version    1.5
 */
public class IOControl extends Object {
    private Process process;
    private BufferedReader stdout;
    private BufferedReader stderr;
    private PrintStream stdin;

    /**
     *  Constructor for the IOControl object
     *
     * @param  process  The process to control I/O for
     */
    public IOControl(Process process) {
        this.process = process;
        this.stdin = new PrintStream(process.getOutputStream());
        this.stdout = new BufferedReader(new InputStreamReader(process.getInputStream()));
        this.stderr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
    }

    /**
     *  Gets the stdin attribute of the IOControl object
     *
     * @return    The stdin value
     */
    public PrintStream getStdin() {
        return this.stdin;
    }

    /**
     *  Gets the stdout attribute of the IOControl object
     *
     * @return    The stdout value
     */
    public BufferedReader getStdout() {
        return this.stdout;
    }

    /**
     *  Gets the stderr attribute of the IOControl object
     *
     * @return    The stderr value
     */
    public BufferedReader getStderr() {
        return this.stderr;
    }

    /**
     *  Gets the process attribute of the IOControl object. To monitor the process (as opposed to
     *  just letting it run by itself) its necessary to create a thread like this: <pre>
     *. IOControl ioc;
     *.
     *. new Thread(){
     *.     public void run(){
     *.         while(true){    // only necessary if you want the process to respawn
     *.             try{
     *.                 ioc = new IOControl(Runtime.getRuntime().exec("procname"));
     *.                 // add some code to handle the IO streams
     *.                 ioc.getProcess().waitFor();
     *.             }catch(InterruptedException ie){
     *.                 // deal with exception
     *.             }catch(IOException ioe){
     *.                 // deal with exception
     *.             }
     *.
     *.             // a break condition can be included here to terminate the loop
     *.         }               // only necessary if you want the process to respawn
     *.     }
     *. }.start();
     *  </pre>
     *
     * @return    The process value
     */
    public Process getProcess() {
        return this.process;
    }
}
dsm
  • 10,263
  • 1
  • 38
  • 72
4

Don't forget Tcl:

set result [exec ls]
Dave Ray
  • 39,616
  • 7
  • 83
  • 82
4

C# 3.0, less verbose than this one:

using System;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        var info = new ProcessStartInfo("cmd", "/c dir") { UseShellExecute = false, RedirectStandardOutput = true };
        Console.WriteLine(Process.Start(info).StandardOutput.ReadToEnd());
    }
}

Caveat: Production code should properly dispose the Process object...

Community
  • 1
  • 1
3

Here's another Lisp way:

(defun execute (program parameters &optional (buffer-size 1000))
  (let ((proc (sb-ext:run-program program parameters :search t :output :stream))
        (output (make-array buffer-size :adjustable t :fill-pointer t 
                            :element-type 'character)))
    (with-open-stream (stream (sb-ext:process-output proc))
      (setf (fill-pointer output) (read-sequence output stream)))
    output))

Then, to get your string:

(execute "cat" '("/etc/hosts"))

If you want to run a command that creates prints a great deal of info to STDOUT, you can run it like this:

(execute "big-writer" '("some" "parameters") 1000000)

The last parameter preallocates a large amount of space for the output from big-writer. I'm guessing this function could be faster than reading the output stream one line at a time.

Donnie Cameron
  • 786
  • 3
  • 13
3

Lua:

    foo = io.popen("ls"):read("*a")
Alexander Gladysh
  • 39,865
  • 32
  • 103
  • 160
3

Perl:

$output = `foo`;

ADDED: This is really a multi-way tie. The above is also valid PHP, and Ruby, for example, uses the same backtick notation as well.

dreeves
  • 26,430
  • 45
  • 154
  • 229
3

In PHP

$output = `ls`;

or

$output = shell_exec('ls');
Leon Timmermans
  • 30,029
  • 2
  • 61
  • 110
3

C (with glibc extension):

#define _GNU_SOURCE
#include <stdio.h>
int main() {
    char *s = NULL;
    FILE *p = popen("ls", "r");
    getdelim(&s, NULL, '\0', p);
    pclose(p);
    printf("%s", s);
    return 0;
}

Okay, not really concise or clean. That's life in C...

ephemient
  • 198,619
  • 38
  • 280
  • 391
3

In C on Posix conformant systems:

#include <stdio.h> 

FILE* stream = popen("/path/to/program", "rw");
fprintf(stream, "foo\n"); /* Use like you would a file stream. */
fclose(stream);
mstrobl
  • 2,381
  • 14
  • 16
3

Why there is still no c# guy here :)

This is how to do it in C#. The built-in way.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Process p = new Process();

            p.StartInfo.UseShellExecute = false;
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.FileName = "cmd";
            p.StartInfo.Arguments = "/c dir";
            p.Start();

            string res = p.StandardOutput.ReadToEnd();
            Console.WriteLine(res);
        }

    }
}
Gant
  • 29,661
  • 6
  • 46
  • 65
2

Clozure Common Lisp:

(with-output-to-string (stream)
   (run-program "ls" '("-l") :output stream))

LispWorks

(with-output-to-string (*standard-output*)
  (sys:call-system-showing-output "ls -l" :prefix "" :show-cmd nil))
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
2

J:

output=:2!:0'ls'
ephemient
  • 198,619
  • 38
  • 280
  • 391
2

Perl, another way:

use IPC::Run3

my ($stdout, $stderr);
run3 ['ls'], undef, \$stdout, \$stderr
    or die "ls failed";

Useful because you can feed the command input, and get back both stderr and stdout separately. Nowhere near as neat/scary/slow/disturbing as IPC::Run, which can set up pipes to subroutines.

derobert
  • 49,731
  • 15
  • 94
  • 124
2

Icon/Unicon:

stream := open("ls", "p")
while line := read(stream) do { 
    # stuff
}

The docs call this a pipe. One of the good things is that it makes the output look like you're just reading a file. It also means you can write to the app's stdin, if you must.

staticsan
  • 29,935
  • 4
  • 60
  • 73
0

Granted, it is not the smaller ( from all the languages available ) but it shouldn't be that verbose.

This version is dirty. Exceptions should be handled, reading may be improved. This is just to show how a java version could start.

Process p = Runtime.getRuntime().exec( "cmd /c " + command );
InputStream i = p.getInputStream();
StringBuilder sb = new StringBuilder();
for(  int c = 0 ; ( c =  i.read() ) > -1  ; ) {
    sb.append( ( char ) c );
}

Complete program below.

import java.io.*;

public class Test { 
    public static void main ( String [] args ) throws IOException { 
        String result = execute( args[0] );
        System.out.println( result );
    }
    private static String execute( String command ) throws IOException  { 
        Process p = Runtime.getRuntime().exec( "cmd /c " + command );
        InputStream i = p.getInputStream();
        StringBuilder sb = new StringBuilder();
        for(  int c = 0 ; ( c =  i.read() ) > -1  ; ) {
            sb.append( ( char ) c );
        }
        i.close();
        return sb.toString();
    }
}

Sample ouput ( using the type command )

C:\oreyes\samples\java\readinput>java Test "type hello.txt"
This is a sample file
with some
lines

Sample output ( dir )

 C:\oreyes\samples\java\readinput>java Test "dir"
 El volumen de la unidad C no tiene etiqueta.
 El número de serie del volumen es:

 Directorio de C:\oreyes\samples\java\readinput

12/16/2008  05:51 PM    <DIR>          .
12/16/2008  05:51 PM    <DIR>          ..
12/16/2008  05:50 PM                42 hello.txt
12/16/2008  05:38 PM             1,209 Test.class
12/16/2008  05:47 PM               682 Test.java
               3 archivos          1,933 bytes
               2 dirs            840 bytes libres

Try any

java Test netstat
java Test tasklist
java Test "taskkill /pid 416"

EDIT

I must admit I'm not 100% sure this is the "best" way to do it. Feel free to post references and/or code to show how can it be improved or what's wrong with this.

OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • "I cannot figure out why nobody posted a Java solution already." Other than VonC and dsm? ;) – Michael Myers Dec 17 '08 at 20:17
  • Well I mean, a real solution. dms ended up with "Now you just have to: while((String s = stdout.readLine())!=null){...}:" Which is the question in first place. And VonC posted a lot of code that make everyone believe Java is that fat ( it is verbose but not that much! ) It takes only 5 lines aprox. – OscarRyz Dec 17 '08 at 21:47
  • -1 This solution can cause a deadlock. You must read stdout (and probably stderr) in a thread. – Aaron Digulla May 25 '09 at 09:19
  • @Aaron: Really?! I don't see how, I've tried several small commands and never got a deadlock. But probably I'm missing something. Please post the problematic command or a way to produce the deadlock. – OscarRyz May 25 '09 at 15:11
  • http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=2 mentions: "The JDK's Javadoc documentation provides the answer to this question: Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.". – hlovdal Jun 24 '09 at 13:17
  • @hlovdal: The posted article dates 2000, when Java 1.2 was the main installation and Java 1.3 had a few months released ( and everyone complain java being very slow - and it was indeed - ) 9 yrs have passed, I hope that situation doesn't show up anymore. Still your point is valid, I can't guarantee this is 100% safe. I guess we should stress it for a while :) – OscarRyz Jun 25 '09 at 16:40
  • Wanted to add something for pipelines in Linux/Unix: Java exec doesn't actually run anything in the shell, so you need to invoke a shell first. Instead of a command String, use a String[] command = {"/bin/bash", "-c", "ps -ef | grep java"} to do this. – Chthonic Project Feb 27 '13 at 20:10