Pregunta

Perl y PHP hacen esto con backticks. Por ejemplo,

$output = `ls`;

Devuelve una lista de directorio. Una función similar, system("foo"), devuelve el código de retorno del sistema operativo para el comando dado foo. Estoy hablando de una variante que devuelve lo que Foo imprime a stdout.

¿Cómo hacen esto otros idiomas? ¿Hay un nombre canónico para esta función? (Voy con & Quot; backtick & Quot ;; aunque tal vez podría acuñar & Quot; syslurp & Quot ;.)

¿Fue útil?

Solución 20

Perl:

$output = `foo`;

AGREGADO: Esto es realmente un empate multidireccional. Lo anterior también es PHP válido, y Ruby, por ejemplo, también usa la misma notación de retroceso.

Otros consejos

Python

from subprocess import check_output as qx

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

Python < 2.7 o lt; 3.1

Extracto subprocess.check_output() de subprocess.py o adaptar algo similar a:

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())

El subproceso ha estado en stdlib desde 2.4.

Python:

import os
output = os.popen("foo").read()

[A pedido de Alexman y dreeves - ver comentarios -, encontrará en este Página DZones Java Snippet una versión completa independiente de Os para hacer, en este caso, un 'ls'. Esta es una respuesta directa a su código-desafío .
Lo que sigue a continuación es solo el núcleo: Runtime.exec, más 2 hilos para escuchar stdout y stderr. ]

Java " Simple! " ;:

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

O en código java

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

Pero para hacer eso, necesitas codificar ...
... esto es embarazoso.

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

Otra forma de hacerlo en Perl (TIMTOWTDI)

$output = <<`END`;
ls
END

Esto es especialmente útil cuando se incrusta un script de shell relativamente grande en un programa Perl

Ruby: ya sea backticks o la sintaxis incorporada '% x'.

puts `ls`;
puts %x{ls};

Un método alternativo en perl

$output = qx/ls/;

Esto tiene la ventaja de que puede elegir sus delimitadores, lo que hace posible usar `en el comando (aunque en mi humilde opinión, debe reconsiderar su diseño si realmente necesita hacerlo). Otra ventaja importante es que si usa comillas simples como delimitador, las variables no se interpolarán (una muy útil)

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

Con MissingH instalado:

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

Esta es una operación fácil en " glue " idiomas como Perl y Ruby, pero Haskell no lo es.

En shell

OUTPUT=`ls`

o alternativamente

OUTPUT=$(ls)

Este segundo método es mejor porque permite anidar, pero no es compatible con todos los shells, a diferencia del primer método.

Erlang:

os:cmd("ls")

Bueno, dado que esto depende del sistema, hay muchos idiomas que no tienen un contenedor incorporado para las diversas llamadas al sistema necesarias.

Por ejemplo, Common Lisp en sí no fue diseñado para ejecutarse en ningún sistema específico. Sin embargo, SBCL (la implementación de Common Banks Common Lisp) proporciona una extensión para sistemas tipo Unix, al igual que la mayoría de las otras implementaciones de CL. Esto es mucho más & Quot; poderoso & Quot; que solo obtener el resultado, por supuesto (usted tiene control sobre el proceso de ejecución, puede especificar todo tipo de direcciones de flujo, etc., consulte el manual SBCL, capítulo 6.3), pero es fácil escribir una pequeña macro para este específico propósito:

(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))

Ahora, puedes usarlo así:

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

Quizás quieras sorberlo todo en una sola cuerda. La macro es trivial (aunque quizás sea posible un código más conciso):

(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)))))))

Ahora puede obtener una cadena con esta llamada:

(syslurp "ls" '("-l"))

Mathematica:

output = Import["!foo", "Text"];

Hace años escribí un plugin para jEdit que se conecta a una aplicación nativa. Esto es lo que solía quitar las transmisiones del ejecutable en ejecución. Lo único que queda por hacer es 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;
    }
}

No olvides Tcl:

set result [exec ls]

C # 3.0, menos detallado que este :

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

Advertencia: el código de producción debe disponer correctamente el objeto Proceso ...

Otra forma (¡o 2!) en Perl ...

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

abierto también se puede escribir así ...

open my $pipe, '-|', 'ps'

En PHP

$output = `ls`;

o

$output = shell_exec('ls');

C (con glibc extensión):

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

Bien, no muy conciso o limpio. Así es la vida en C ...

En C en sistemas conformes con Posix:

#include <stdio.h> 

FILE* stream = popen("/path/to/program", "rw");
fprintf(stream, "foo\n"); /* Use like you would a file stream. */
fclose(stream);

¿Por qué todavía no hay un chico de C # aquí?

Así es como se hace en C #. La forma integrada.

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

    }
}

Aquí hay otra forma de Lisp:

(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))

Luego, para obtener su cadena:

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

Si desea ejecutar un comando que crea imprime una gran cantidad de información en STDOUT, puede ejecutarlo así:

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

El último parámetro asigna previamente una gran cantidad de espacio para la salida de big-writer. Supongo que esta función podría ser más rápida que leer el flujo de salida una línea a la vez.

Lua :

    foo = io.popen("ls"):read("*a")

J :

output=:2!:0'ls'

Perl, otra forma:

use IPC::Run3

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

Útil porque puede alimentar la entrada del comando y recuperar tanto stderr como stdout por separado. En ningún lugar tan ordenado / aterrador / lento / inquietante como IPC::Run, que puede configurar tuberías para subrutinas.

Icono / Unicon:

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

Los documentos llaman a esto una tubería. Una de las cosas buenas es que hace que la salida parezca que solo estás leyendo un archivo. También significa que puede escribir en el stdin de la aplicación, si es necesario.

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

De acuerdo, no es el más pequeño (de todos los idiomas disponibles) pero no debería ser tan detallado.

Esta versión está sucia. Se deben manejar las excepciones, se puede mejorar la lectura. Esto es solo para mostrar cómo podría comenzar una versión de Java.

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

Programa completo a continuación.

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

Salida de muestra (usando el comando de tipo)

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

Salida de muestra (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

Pruebe cualquiera

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

EDIT

Debo admitir que no estoy 100% seguro de que este sea el " el mejor " manera de hacerlo. Siéntase libre de publicar referencias y / o código para mostrar cómo se puede mejorar o qué tiene de malo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top