Ubuntu – How to tell which parameter is being supplied to a command with a redirectioin operator

bashcommand line

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?

Best Answer

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.

Related Question