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?

Braiam
  • 66,947
  • 30
  • 177
  • 264
vlad-ardelean
  • 347
  • 3
  • 12
  • 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 '14 at 18:56

2 Answers2

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.

terdon
  • 98,183
  • 15
  • 197
  • 293
  • 1
    Nice answer! very thorough (especially including the differences between the file redirectors) – steeldriver Apr 14 '14 at 19:25
  • @steeldriver aww, shucks, thanks :) And so was [this](http://askubuntu.com/a/447485/85695) 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 '14 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 '14 at 10:12
  • @Aditya done. And don't worry, it stops at `<<<` :) – terdon Apr 15 '14 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"
steeldriver
  • 131,985
  • 21
  • 239
  • 326
  • 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.se]. We live and die for cool shell tricks over there.. – terdon Apr 14 '14 at 19:10
  • @terdon: same thing for perl golfers? – Sylvain Pineau Apr 14 '14 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](http://unix.stackexchange.com/users/885/gilles) [of](http://unix.stackexchange.com/users/22565/stephane-chazelas) [whom](http://unix.stackexchange.com/users/7453/slm) are absurdly knowledgeable. – terdon Apr 14 '14 at 19:18