Get system command output: Difference between revisions

From Rosetta Code
Content added Content deleted
mNo edit summary
Line 522: Line 522:
This is usually not necessary except when dealing with binary data output.
This is usually not necessary except when dealing with binary data output.


=={{header|vbscript}}==
=={{header|VBScript}}==
This program implements a function that executes a DOS command and returns
This program implements a function that executes a DOS command and returns the output to the caller.
<lang vb>For Each line In ExecCmd("ipconfig /all")
the output to the caller.
<lang vbscript>
for each line in ExecCmd("ipconfig /all")
Wscript.Echo line
Wscript.Echo line
Next
next


'Execute the given command and return the output in a text array.
'Execute the given command and return the output in a text array.
Function ExecCmd(cmd)

Function ExecCmd ( cmd )


'Execute the command
'Execute the command
Dim wso : Set wso = CreateObject("Wscript.Shell")

dim wso: set wso = CreateObject("Wscript.Shell")
Dim exec : Set exec = wso.Exec(cmd)
dim exec: set exec = wso.Exec(cmd)
Dim res : res = ""
dim res : res = ""


'Read all result text from standard output
'Read all result text from standard output
Do

do: res = res & vbLf & exec.StdOut.ReadLine
res = res & VbLf & exec.StdOut.ReadLine
loop until exec.StdOut.AtEndOfStream
Loop Until exec.StdOut.AtEndOfStream


'Return as a text array
'Return as a text array

ExecCmd = Split(Mid(res,2),vbLf)
ExecCmd = Split(Mid(res,2),vbLf)
End Function</lang>

End Function
</lang>


=={{header|Ursa}}==
=={{header|Ursa}}==

Revision as of 13:09, 14 January 2017

Task
Get system command output
You are encouraged to solve this task according to the task description, using any language you may know.
Task

Execute a system command and get its output into the program. The output may be stored in any kind of collection (array, list, etc.).

Related tasks



AWK

<lang AWK> BEGIN {

        # For Windows
        out = system2var("dir")
        print out
        # Non-Windows
        out = getline2var("ls -l")
        print out

}

  1. For a Windows environment using system() method

function system2var(command ,tempfile, cmd, out, rec, data, i) {

        tempfile = "C:\\TEMP\\TMP.TMP"
        cmd = command " > " tempfile
        system(cmd)
        close(cmd)
        while (getline rec < tempfile > 0) {
            if ( ++i == 1 )
                data = rec
            else
                data = data "\n" rec
        }
        return(data)

}

  1. If command returns an ERRNO function returns null string

function getline2var(command ,fish, scale, ship) {

        command = command " 2>/dev/null"
        while ( (command | getline fish) > 0 ) {
            if ( ++scale == 1 )
                ship = fish
            else
                ship = ship "\n" fish
        }
        close(command)
        return ship

}</lang>

C

<lang C>

  1. include <stdio.h>
  2. include <stdlib.h>
  3. include <string.h>

int main(int argc, char **argv) {

   if (argc < 2) return 1;
   FILE *fd;
   fd = popen(argv[1], "r");
   if (!fd) return 1;
   char   buffer[256];
   size_t chread;
   /* String to store entire command contents in */
   size_t comalloc = 256;
   size_t comlen   = 0;
   char  *comout   = malloc(comalloc);
   /* Use fread so binary data is dealt with correctly */
   while ((chread = fread(buffer, 1, sizeof(buffer), fd)) != 0) {
       if (comlen + chread >= comalloc) {
           comalloc *= 2;
           comout = realloc(comout, comalloc);
       }
       memmove(comout + comlen, buffer, chread);
       comlen += chread;
   }
   /* We can now work with the output as we please. Just print
    * out to confirm output is as expected */
   fwrite(comout, 1, comlen, stdout);
   free(comout);
   pclose(fd);
   return 0;

} </lang>

Common Lisp

Library: trivial-shell

<lang lisp>(trivial-shell:shell-command "uname -imp")</lang>

Output:
"x86_64 AMD A10-5750M APU with Radeon(tm) HD Graphics AuthenticAMD

We can also use functions specific to Common Lisp implementations. In SBCL, we have RUN-PROGRAM, which returns a process object. This object will contain an output stream if we use the :output keyword. We can then read from the stream:

<lang lisp>(defparameter *my-proc*

 (sb-ext:run-program "mplayer" (list "/path/to/groovy/tune")
                     :search t :output :stream :wait nil))

(read-line (sb-ext:process-output *my-proc*) nil)</lang>

FreeBASIC

<lang freebasic>' FB 1.05.0 Win64

'capture the output of the 'dir' command and print it to a text file

Open "dir_output.txt" For Output As #1 Open Pipe "dir" For Input As #2 Dim li As String

While Not Eof(2)

 Line Input #2, li
 Print #1, li

Wend

Close #2 Close #1 End</lang>

Go

<lang go>package main

import (

 "fmt"
 "log"
 "os/exec"

)

func main() {

 output, err := exec.Command("ls", "-l").CombinedOutput()
 if err != nil {
   log.Fatal(err)
 }
 fmt.Print(string(output))

}</lang>

Icon and Unicon

<lang unicon>#

  1. piped.icn, Get system command output
  2. Dedicated to the public domain

procedure main()

   # start with an empty list
   directory := []
   # ls for UNIX, dir for other, assume Windows
   command := if &features == "UNIX" then "ls" else "dir"
   # open command in pipe mode
   p := open(command, "p") | stop("Cannot open pipe for ", command)
   # read in results and append to list
   while put(directory, read(p))
   # display the fifth entry, if there is one
   write(\directory[5])
   close(p)

end</lang>

Output:
prompt$ unicon -s piped.icn -x
piped.u

J

We will box the result of uname -imp on a linux system, to show that we have captured the command output in J:

<lang J> require 'task'

  <shell 'uname -imp'

┌─────────────────────┐ │x86_64 x86_64 x86_64 │ └─────────────────────┘</lang>

Caution: I have sometimes seen some versions of linux refuse to execute subshells after a few hundred thousand shell commands (the exec system call fails). I've not found any satisfying documentation on why this happens, but I strongly suspect kernel memory fragmentation (the examples where this happened were also using a lot of memory to accumulate results and it happened much more frequently an machines with little memory than on machines with more memory). Exiting J and starting a new process has cleared it up when it has happened. Anyways, I usually prefer to do that kind of processing before J starts, just to be safe.

(I've seen other problems on windows and osx - I am only singling out linux here because it is the most convenient for command line and system command use.)

Java

Works with: Java version 7

<lang java>import java.io.*; import java.util.*;

public class SystemCommand {

   public static void main(String args[]) throws IOException {
       String command = "cmd /c dir";
       Process p = Runtime.getRuntime().exec(command);
       try (Scanner sc = new Scanner(p.getInputStream())) {
           System.out.printf("Output of the command: %s %n%n", command);
           while (sc.hasNext()) {
               System.out.println(sc.nextLine());
           }
       }
   }

}</lang>

Output:

Output of the command: cmd /c dir 

 Het volume in station C heeft geen naam.
 Het volumenummer is 10CE-30C3

 Map van C:\projects\SystemCommand

30-06-2014  00:48    <DIR>          .
30-06-2014  00:48    <DIR>          ..
30-06-2014  00:48    <DIR>          build
30-06-2014  00:46             3.624 build.xml
30-06-2014  00:48    <DIR>          dist
30-06-2014  00:46                85 manifest.mf
30-06-2014  00:46    <DIR>          nbproject
30-06-2014  00:46    <DIR>          src
               2 bestand(en)            3.709 bytes
               6 map(pen)  756.833.009.664 bytes beschikbaar

Lingo

Library: Shell Xtra

<lang lingo>sx = xtra("Shell").new() put sx.shell_cmd("cd C:\dev\lsw\lib & dir")

-- " <snip> 31.08.2016 21:25 <DIR> . 31.08.2016 21:25 <DIR> .. 20.08.2016 04:58 <DIR> aes 23.06.2016 18:23 <DIR> audio 21.07.2016 19:19 <DIR> avmedia 23.06.2016 18:22 <DIR> base64 23.06.2016 18:21 <DIR> base9 <snip>"</lang>

Lua

<lang Lua>local output = io.popen("echo Hurrah!") print(output:read("*all"))</lang>

Output:
Hurrah!

ooRexx

<lang ooRexx>/* Execute a system command and retrieve its output into a stem. */

 trace normal

/* Make the default values for the stem null strings. */

 text. = 

/* Issue the system command. "address command" is optional.) */

 address command 'ls -l | rxqueue'

/* Remember the return code from the command. */

 ls_rc = rc

/* Remember the number of lines created by the command. */

 text.0 = queued()

/* Fetch each line into a stem variable. */

 do t = 1 to text.0
   parse pull text.t
 end

/* Output each line in reverse order. */

 do t = text.0 to 1 by -1
   say text.t
 end

/* Exit with the system command's return code. */ exit ls_rc</lang>

PARI/GP

<lang parigp>externstr("time/t")</lang>

Perl

Uses the qx{} construct (which is a synonym for backticks, e.g. `command`) to execute a given command and redirect its output. A (somewhat contrived*) example, capturing only STDOUT: <lang perl>my @directories = grep { -d $_ } `ls`; foreach @directories { chomp; ...; # Operate on directories }</lang>

  • Perl's opendir function should be used in preference to parsing ls--it's safer, faster, and more portable.

Perl also honors shell redirections: <lang perl>my $command = shift or die "No command supplied\n"; my @output_and_errors = qx/$command 2>&1/ or die "Couldn't execute command\n";</lang> qx// is implemented internally with the built-in function readpipe, which can be invoked directly as readpipe EXPR (where EXPR is some command) and assigned to scalars or lists just like qx/command/ or `command`.

The open command can also be used to open pipes using the -| mode: <lang perl>use autodie; my $enc = ':encoding(UTF:8)'; my $child_pid = open(my $pipe, "-|$enc", 'ls'); while (<$pipe>) {

 # Print all files whose names are all lowercase
   print if m/[^A-Z]+/;

}</lang>

Perl 6

If you don't want to execute it in shell (and you probably don't), then use this: <lang perl6>say run($command, $arg1, $arg2, :out).out.slurp-rest;</lang>

Unfortunately, it is very long to type, but that is the only way to pass your variables as arguments safely.

You might be tempted to start using shell when you have to pipe something, but even in that case there is no need to do so. See this code: <lang perl6>my $p1 = run 'echo', 'Hello, world', :out; my $p2 = run 'cat', '-n', :in($p1.out), :out; say $p2.out.slurp-rest;</lang> See docs for more info.

If you really want to run something in shell and you understand potential security problems, then you can use qx// (interpolates environment variables) or qqx// (interpolates normally). See the docs for more info.

<lang perl6>say qx[dir]</lang>

Output:
Find_URI_in_text.p6  History_variables.p6  K-d_tree.pl
Fractran.pl	     History_variables.pl  XML_Input.p6

PicoLisp

<lang PicoLisp>: (in '(uname "-om") (line T)) -> "aarch64 Android"</lang>

PowerShell

Capture system disk label information as an array of strings: <lang PowerShell> [string[]]$volume = cmd /c vol

$volume </lang>

Output:
 Volume in drive C is Ordo-Xenos
 Volume Serial Number is 8C33-162D

Python

<lang python>>>> import subprocess >>> returned_text = subprocess.check_output("dir", shell=True, universal_newlines=True) >>> type(returned_text) <class 'str'> >>> print(returned_text)

Volume in drive C is Windows
Volume Serial Number is 44X7-73CE
Directory of C:\Python33

04/07/2013 06:40 <DIR> . 04/07/2013 06:40 <DIR> .. 27/05/2013 07:10 <DIR> DLLs 27/05/2013 07:10 <DIR> Doc 27/05/2013 07:10 <DIR> include 27/05/2013 07:10 <DIR> Lib 27/05/2013 07:10 <DIR> libs 16/05/2013 00:15 33,326 LICENSE.txt 15/05/2013 22:49 214,554 NEWS.txt 16/05/2013 00:03 26,624 python.exe 16/05/2013 00:03 27,136 pythonw.exe 15/05/2013 22:49 6,701 README.txt 27/05/2013 07:10 <DIR> tcl 27/05/2013 07:10 <DIR> Tools 16/05/2013 00:02 43,008 w9xpopen.exe

              6 File(s)        351,349 bytes
              9 Dir(s)  46,326,947,840 bytes free

>>> # Ref: https://docs.python.org/3/library/subprocess.html</lang>

Racket

We use #lang racket/base to show which module system is in. It would be imported anyway if we use the larger #lang racket.

This demonstrates one function: system</system>. It is the simplest of a family of commands in the racket/system collection.

See documentation for system and friends.

<lang racket>#lang racket/base

(require racket/system

        (only-in racket/port with-output-to-string)
        tests/eli-tester)

(test

;; system runs command and outputs to current output port (which is stdout unless we catch it)
(system "ls /etc/motd") => #t
;; it throws an error on non-zero exit code (so I need to catch it in this error handler)
(system "false") => #f       ; nothing printed to stdout/stderr
(system "ls /etc/mosh") => #f ; error report printed to stderr 
;; output can be captured by redirecting stdout/stderr (which are known as current-output-port and
;; current-error-port in racket parlance).
;; the command printed a \n, so there is a newline captured by the system command
(with-output-to-string (λ () (system "ls /etc/motd"))) => "/etc/motd\n"
;; no \n is captured when none is captured
(with-output-to-string (λ () (system "echo -n foo"))) => "foo"
;; error is still not captured (it's still printed to stderr)
(with-output-to-string (λ () (system "echo -n foo; echo bar 1>&2"))) => "foo"
;; we can capture both with:
(let* ((out-str-port (open-output-string))
       (err-str-port (open-output-string))
       (system-rv
        (parameterize ((current-output-port out-str-port) (current-error-port err-str-port))
          (system "echo -n foo; echo bar 1>&2"))))
  (values system-rv (get-output-string out-str-port) (get-output-string err-str-port)))
=> (values #t "foo" "bar\n"))</lang>
Output:
/etc/motd

the following goes to standard error:

ls: /etc/mosh: No such file or directory
bar

and back to standard output:

7 tests passed

REXX

Works with: Regina

<lang rexx>/*REXX program executes a system command and displays the results (from an array). */ trace off /*suppress REXX error msgs for fails. */ @.=0 /*assign default in case ADDRESS fails.*/ address system arg(1) with output stem @. /*issue/execute the command and parms. */ if rc\==0 then say copies('─', 40) 'return code ' rc " from: " arg(1)

                                                /* [↑]  tell if an error occurred.     */
          do j=1  for @.0                       /*display the output from the command. */
          say strip(@.j, 'T')                   /*display one line at a time-->terminal*/
          end   /*out*/                         /* [↑]  displays all the output.       */

exit 0 /*stick a fork in it, we're all done. */</lang> output from the executed command:   dir g:sub*.2*   under Windows/XP:

 Volume in drive G is -----G-----
 Volume Serial Number is 6826-1B4B

 Directory of G:\

05/22/2012  08:27                30 SUBSET.2
05/24/2012  03:55         2,117,571 SUBSET.20
05/24/2012  03:55         1,132,068 SUBSET.21
05/24/2012  09:56           522,155 SUBSET.22
05/24/2012  09:56           193,293 SUBSET.23
05/24/2012  09:56            71,931 SUBSET.24
05/24/2012  09:56            15,995 SUBSET.25
05/24/2012  09:56             3,188 SUBSET.26
05/24/2012  09:56               471 SUBSET.27
               9 File(s)      4,056,702 bytes
               0 Dir(s)  18,252,660,736 bytes free

Ring

<lang ring> system("dir C:\Ring\doc") </lang> Output:

 Volume in drive C is Helyi lemez
 Volume Serial Number is F0B2-B1C8

 Directory of C:\Ring\doc

2016. 04. 05.  17:19    <DIR>          .
2016. 04. 05.  17:19    <DIR>          ..
2016. 04. 07.  07:44         3 276 076 Fayed_RingDoc_1.0.chm
2016. 04. 06.  19:00         5 371 211 Fayed_RingDoc_1.0.pdf
               2 File(s)      8 647 287 bytes
               2 Dir(s)  949 801 435 136 bytes free

Run BASIC

<lang runbasic>a$ = shell$("dir") ' Returns the directory info into a$ print a$ ' prints the directory </lang>

Ruby

Many options, google exec or system or %x. Demonstrating backticks: <lang ruby>str = `ls` arr = `ls`.lines</lang>

Rust

<lang rust>use std::process::Command; use std::io::{Write, self};

fn main() {

   let output = Command::new("/bin/cat")
                           .arg("/etc/fstab")
                           .output()
                           .expect("failed to execute process");
   io::stdout().write(&output.stdout);

}</lang>

Sidef

Using backticks: <lang ruby>var output = `ls`; # `output` is a string var lines = `ls`.lines; # `lines` is an array</lang>

Using pipes: <lang ruby>var pipe = %p(ls); # same as: Pipe.new('ls'); var pipe_h = pipe.open_r; # open the pipe for reading var lines = []; # will store the lines of the output pipe_h.each { |line| lines.append(line.chomp) };</lang>

Tcl

The exec makes this straight-forward for most commands. <lang tcl>set data [exec ls -l] puts "read [string length $data] bytes and [llength [split $data \n]] lines"</lang> There are a few exceptions, such as the DIR command on Windows, where they need to be run slightly differently due to being system shell builtins rather than executables. In that case, the auto_execok standard library command is used to look up how to run the command (strictly it can be used for any command — it will do path resolution, etc. — but is only necessary for system builtins). <lang tcl>set data [exec {*}[auto_execok DIR]]</lang> By default, Tcl will use the system encoding (as reported by encoding system) to understand the output byte-stream as characters, and will auto-convert all the various types of newline terminators into U+00000A characters. Control over this is possible by launching the subprocess as a pipe, configuring the pipe, and then reading the pipe in its entirety. <lang tcl># This syntax is pretty ugly, alas set pipe [open |[list ls -l] "r"] fconfigure $pipe -encoding iso8859-1 -translation lf set data [read $pipe] close $pipe</lang> This is usually not necessary except when dealing with binary data output.

VBScript

This program implements a function that executes a DOS command and returns the output to the caller. <lang vb>For Each line In ExecCmd("ipconfig /all")

   Wscript.Echo line

Next

'Execute the given command and return the output in a text array. Function ExecCmd(cmd)

   'Execute the command
   Dim wso : Set wso = CreateObject("Wscript.Shell")
   Dim exec : Set exec = wso.Exec(cmd)
   Dim res : res = ""
   'Read all result text from standard output
   Do
       res = res & VbLf & exec.StdOut.ReadLine
   Loop Until exec.StdOut.AtEndOfStream
   'Return as a text array
   ExecCmd = Split(Mid(res,2),vbLf)

End Function</lang>

Ursa

This program reads the output of the ifconfig command into the string stream 'output', then writes it to the screen. <lang ursa>> decl iodevice iod > decl string<> arg > append "ifconfig" arg > set iod (ursa.util.process.start arg) > decl string<> output > set output (iod.readlines) > for (decl int i) (< i (size output)) (inc i) .. out output endl console ..end for lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 options=3<RXCSUM,TXCSUM> inet6 ::1 prefixlen 128 inet 127.0.0.1 netmask 0xff000000 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 nd6 options=1<PERFORMNUD> gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280 stf0: flags=0<> mtu 1280 en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 options=27<RXCSUM,TXCSUM,VLAN_MTU,TSO4> ether d4:9a:20:b8:8d:2c nd6 options=1<PERFORMNUD> media: autoselect status: inactive en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether 00:26:08:e0:67:cc inet6 fe80::226:8ff:fee0:67cc%en1 prefixlen 64 scopeid 0x5 inet 172.20.30.66 netmask 0xffffff00 broadcast 172.20.30.255 nd6 options=1<PERFORMNUD> media: autoselect status: active fw0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 4078 lladdr d4:9a:20:ff:fe:b8:8d:2c nd6 options=1<PERFORMNUD> media: autoselect <full-duplex> status: inactive p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304 ether 02:26:08:e0:67:cc media: autoselect status: inactive > </lang>

zkl

From the REPL on Linux. Runs a command in the shell with stdout redirected to file, then slurps the file. A bit greasy since there isn't a way to find/generate a unique unused file name. <lang zkl>zkl: System.cmd("date >foo.txt") 0 // date return code zkl: File("foo.txt").read().text Wed Aug 20 00:28:55 PDT 2014</lang>