views:

2618

answers:

27

Perl and PHP do this with backticks. For example:

$output = `ls`;

This code returns a directory listing into the variable $output. A similar function, system("ls"), returns the operating system return code for the given command. I'm talking about a variant that returns whatever the command prints to stdout. (There are better ways to get the list of files in a directory; the example code is an example of this concept.)

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".)

+3  A: 

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
+4  A: 

Mathematica:

output = Import["!foo", "Text"];
dreeves
+8  A: 

Python:

import os
output = os.popen("foo").read()
dreeves
The semicolons are not necessary.
J.F. Sebastian
gone. perl still wins by character count :)
dreeves
when did this turn into code golf? :)
Jeremy Cantrell
It would have turned into code golf when Perl was invented, but APL was ahead of Perl.
Windows programmer
As of python 2.5, you should use the subprocess module.
Aaron Digulla
+6  A: 

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
Actually, you can nest using backticks, but you don't want to go there.
Leon Timmermans
You can nest backticks if you escape them, but it gets ugly really fast.
Adam Rosenfield
Dudes .. shell script *is* ugly.
troelskn
Anyone who can declare variables in C-based languages can escape backticks and escapes in shell scripts.
Windows programmer
+6  A: 

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

puts `ls`;
puts %x{ls};
Ovid
+3  A: 

In PHP

$output = `ls`;

or

$output = shell_exec('ls');
Leon Timmermans
+7  A: 

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
That's the same method, backticks are just syntactic sugar for this.
Svante
+6  A: 

Erlang:

os:cmd("ls")
JesperE
Is the stdout captured or directed to caller's stdout?
eduffy
It's captured and returned as a string.
JesperE
+7  A: 

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
IT's not really a different way, as know you. It's just using different quoting mechanisms. :)
brian d foy
True, but I'm having the impression few people know about this trick
Leon Timmermans
I think that there is a semicolon missing after the first line.
Svante
"embedding a relatively large shell script in a Perl program" - a phrase which will surely be the source of many nightmares to come for me!
Dave Rolsky
+6  A: 

[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;
    }
}
VonC
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
Done: String output = GoodWindowsExec.execute("dir");
VonC
Where's the AbstractFactoryBuilderFactory.buildExecFactory() call?
Axeman
VonC
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
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
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
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
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
Java. The most verbose language known to man.
Paul Nathan
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
"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
+8  A: 

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.

J.F. Sebastian
@JF: It's not in my 2.6.2, but the linked docs do say 2.7 and 3.1.
Roger Pate
+1 for this solution because I'm using Python 2.5 and the check_output function is not available.
Simone Carletti
+4  A: 

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'

/I3az/

draegtun
I was thinking of that one too, but I don't think the "various languages" part of this thread is getting done.
Axeman
There should be a `smoke my $pipe;` in perl...
David Schmitt
+2  A: 

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
Concise (as C can be for this sort of thing), but not portable and also leaks memory.
Adam Rosenfield
+2  A: 

J:

output=:2!:0'ls'
ephemient
+5  A: 

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
That was helpful.
CiscoIPPhone
+4  A: 

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
+3  A: 

Don't forget Tcl:

set result [exec ls]
Dave Ray
+6  A: 
Svante
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
Oh, there are many libraries. Some regarding system interaction are listed at http://www.cliki.net/compatibility%20layers
Svante
+2  A: 

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
+2  A: 

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
A: 

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
"I cannot figure out why nobody posted a Java solution already." Other than VonC and dsm? ;)
Michael Myers
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
-1 This solution can cause a deadlock. You must read stdout (and probably stderr) in a thread.
Aaron Digulla
@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
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
@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
+3  A: 

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);
        }

    }
}
m3rLinEz
Are you trying to make c# look bad? :)
Kobi
+2  A: 

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
+4  A: 

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...

Andreas Huber
+3  A: 

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
+2  A: 

Lua:

    foo = io.popen("ls"):read("*a")
Alexander Gladysh
+2  A: 

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