How can I send characters to a command as though they came from a file?
For example I tried:
wc < "apple pear orange"
-bash: apple pear orange: No such file or directory
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityIn shells that support here strings, including bash
, zsh
and ksh93
, you can use
wc <<< "apple pear orange"
Two other approaches (which allow multiple-line input with no extra effort):
Use a "here document":
$ wc << EOF apple pear orange EOF 1 3 18 $
The EOF
string is a delimiter.
You can use any string; EOF
is just a conventional choice.
Use the tty as the input:
$ wc apple pear orange Ctrl+D 1 3 18 $
This has the drawback that the program starts running, and starts reading the input, as soon as you type its name. This can be disconcerting; for example:
$ grep v The quick brown fox (typed) jumps over (typed) jumps over (This is output from grep!) the lazy dog. (typed) Ctrl+D (No output here) $
<<<
form also allows multiple-line input with no extra effort, since the "
-enclosed string can contain newlines. Of course the << EOF
form (the original here-doc syntax) is easier to read if you have multi-line input.
<<<
word
— of course, in the context of the shell, a word
can be a quoted string, containing spaces and newlines! D’oh! That’s so obvious that it goes without saying (and, in fact, I don’t see it mentioned in the man page at all). :-( Thanks for pointing this out to me!
Jan 31, 2017 at 22:22
word
is defined in the manpage as "A sequence of characters considered as a single unit by the shell" (aka "token"), and you need to know that quoted strings are treated as "a single unit" in the relevant sense (after backslash processing, variable expansion etc." But indeed that's the whole purpose of double-quoting in the shell. (Single quotes also protect from expansion.) The shell's processing model is very well thought out, and anything but simple.
Although there are several valid solutions here, another syntax that can be useful sometimes, is to run a command in <()
. This would allow you to create more than 1 file-descriptor object on a command line.
This can be useful when you're doing something like comparing long strings of text, or if you want to diff some content that's not in a file.
For example, comparing the hosts files on two nodes without having to copy the hosts file to the localhost:
diff -Naur <(cat /etc/hosts) <(ssh -q otherhost 'cat /etc/hosts')
The <
redirects a file to STDIN, and the ()
create a subshell to run the command between the parenthesis. It's the STDOUT from the subshell that is passed to STDIN of the command being run.
It's an easier way to create more than 1 input "file" to a command than trying to use multiple here docs, or trying to echo multiple commands to a pipeline to the final command.
<fileorpathname
redirects stdin, but <(subcmd)
does not; it substitutes a name that when/if opened by the program can read stdout from subcmd. < <(subcmd)
(space required) does redirect stdin from that file, almost like subcmd |
. Your diff
could read one of its inputs from stdin by specifying an argument of -
but not both.
Jan 24, 2017 at 5:46
cmd <(cmd2 ...)
and cmd < <(cmd2 ...)
. The former allows derived data (the output of cmd2) to be used in place a filename. The latter is equivalent to cmd2 ... | cmd
. Commands must be written to explicitly accept stdin input and many are not. This is especially true of shell scripts.
Jan 27, 2017 at 8:44
you can use a pipe
echo "apple pear orange" | wc
You may want to use something similar to expect. Following is a simple example of opening a remote telnet session, waiting for the prompt, send some data, wait for a response, sleep and exit.
#!/usr/bin/expect
spawn telnet localhost 8555
expect "Escape character is '^]'."
send "Hello World\n"
expect "Connection closed by foreign host."
sleep 1