9

This works:

$ echo "notify-send HELLO" | at now

This doesn't:

$ at now < echo "notify-send HELLO"

It says 'file or directory not found".

I understand there's a -f option to this command, which with which i can supply the file to be executed at a given moment.

So this got me thinking... in general, how do i know for which parameter the redirection operators supply the value?

1
  • 5
    Your question is not very clear. What do you mean by "which parameter". Your issue is probably that you (mistakenly) think that foo | bar and bar < foo are equivalent. They are not.
    – terdon
    Apr 14, 2014 at 18:56

2 Answers 2

16

You are using two different things here and should be using a third. Let's see:

  1. | : This is the pipe operator, it serves to pass the output of one process as input to another:

    foo | bar
    

    This runs the program foo and passes its output as input to the program bar.

  2. >,<,>> and <<: These are the redirection operators, they serve to send data to/from files:

    • foo > bar : runs the program foo and saves its output to the file bar, overwriting1 its contents and creating it if it does not exist.

    • foo >> bar : runs the program foo and saves its output to the file bar, appending to its contents and creating it if it does not exist.

    • foo < bar : runs foo, telling it to read input from the file bar.

    • The << is a special case, since there is no point in "appending" input to a command, the << is primarily (exclusively AFAIK) used for Here Documents:

      $ cat << EOF > file.txt
      > Hello World!
      > EOF
      

      The construct << SomeStringHere > Out.file will redirect all text written until it encounters the ending string (EOF in the example above) to the target file. Here docs allow you to easily format multi-line strings and include variables and special characters.

  3. The <<< operator, the Here String, is like a Here Document but it expands variables. So, for example:

    grep foo <<< "$bar"
    

    The command above is equivalent to echo "$bar" | grep foo.

  4. What you are actually looking for is called process substitution and is another way to pass the output of a command to another. It consists of <(command).

    foo <(bar) 
    

    So, for your at example, you could do

    at now < <(echo "notify-send HELLO")
    

    The above works because process substitution actually creates a file (read the link above for more details) and it is the file descriptor of that file that is passed with < to at now.


1 The default behavior is to overwrite, this can be modified by setting the noclobber option to bash. If set, echo foo > bar will fail if bar exists. In that case, it can be forced using echo foo |> bar instead. See section 3.6.2 here.

4
  • 1
    Nice answer! very thorough (especially including the differences between the file redirectors) Apr 14, 2014 at 19:25
  • @steeldriver aww, shucks, thanks :) And so was this under appreciated gem. I wish I could have given you a +1 for each of the various pitfalls your solution silently avoids.
    – terdon
    Apr 14, 2014 at 19:28
  • Could you please also expand to include some information about << and <<< (which @steeldriver mentioned in his answer). Moreover, are there more - something like >>>>>> or <<<<<<<<<<?
    – Aditya
    Apr 15, 2014 at 10:12
  • @Aditya done. And don't worry, it stops at <<< :)
    – terdon
    Apr 15, 2014 at 13:08
12

In this case, echo "notify-send HELLO" is a process not a file - so you need a process substitution rather than a file redirection

at now < <(echo "notify-send HELLO")

You could also have used a here string to avoid the echo command entirely

at now <<< "notify-send HELLO"
3
  • 5
    Having seen the kind of questions you tend to like (same ones I do) I think you should spend some more time over on Unix & Linux. We live and die for cool shell tricks over there..
    – terdon
    Apr 14, 2014 at 19:10
  • @terdon: same thing for perl golfers? Apr 14, 2014 at 19:16
  • 1
    @SylvainPineau oooh yeah. Very much so :). Seriously, the kind of question that you, steeldriver and I enjoy is much more common over there. The place is full of commandline geeks some of whom are absurdly knowledgeable.
    – terdon
    Apr 14, 2014 at 19:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .