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?

  • 4
    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

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.

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

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"
  • 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 '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 of whom are absurdly knowledgeable. – terdon Apr 14 '14 at 19:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.