I would appreciate somebody explaining please why the following does work:

# < /dev/urandom  tr -dc 'a-zA-Z' | head -c 12

There is no '|' before tr , but the following doesn't:

# < /dev/urandom | tr -dc 'a-zA-Z' | head -c 12

(This is a simple password generator)

Could you also please explain how that differs to the following:

# gunzip < HP-Fax4-hpcups.ppd.gz cat > ouT1 --- which of course fails:

gzip: cat.gz: No such file or directory 

if the '|' is left out before the cat; it works however, with the '|' (pipe) before the cat , i.e.

 # gunzip < HP-Fax4-hpcups.ppd.gz | cat >  ouT1
  • If you're happy with one or several of the answers, upvote them. If one is solving your issue, accepting it would be the best way of saying "Thank You!" Accepting an answer also indicates to future readers that the answer actually solved the problem.
    – Kusalananda
    Commented Apr 6, 2018 at 10:23

1 Answer 1

  1. What is <?

    It is redirection of command's INPUT to read FROM a file. You can put it either before or after command:

    $ echo abcd > in
    $ cat in
    $ cat <in
    $ <in cat

    In simple terms, the command reads the file. The difference between cat in and cat <in is that < sets a redirection of STDIN (standard input) for the cat process, while in cat in the in is an argument, and the cat command has to do something with it internally. (Open it, then read it, etc.)

  2. What is |?

    It is redirection to a process. It can only follow a command:

    $ | cat in
    bash: syntax error near unexpected token `|'
    $ cat in | cat
    $ cat in | cat |

    (...and waiting for input...)

  3. What does this do: < /dev/urandom tr -dc 'a-zA-Z' | head -c 12?

    Break it down into smaller pieces (commands with redirections):

    • < /dev/urandom tr -dc 'a-zA-Z' = tr -dc 'a-zA-Z' and < /dev/urandom

      Meaning: do the translation for what you read from urandom.

    • | - redirect to a process using an anonymous pipe

    • head -c 12 - this is the process receiving the redirection

    The whole line makes sense, doesn't it?

  4. What is this: < /dev/urandom | tr -dc 'a-zA-Z' | head -c 12?


    • < /dev/urandom - no command and redirection from /dev/urandom
    • | - redirect to a process using an anonymous pipe
    • tr -dc 'a-zA-Z' - the process receiving the redirection
    • and so on...

    What's wrong here? There's no command in the first "sentence".

  5. What is >?

    This is a redirection of this command's OUTPUT TO a file. Same as <, it can be used before or after a command:

    $ >out echo abcd
    $ cat out
    $ echo dcba >tuo
    $ cat tuo
  6. What's this supposed to do: gunzip < HP-Fax4-hpcups.ppd.gz | cat > ouT1?


    • gunzip < HP-Fax4-hpcups.ppd.gz = redirect from HP-Fax4-hpcups.ppd.gz to gunzip (let gunzip read this file)
    • | - redirect the output to a process
    • cat > ouT1 = cat is the process to receive the redirection and then it's output is redirected to the file ouT1

    This is fine. All the pieces make sense.

  7. What is this then: gunzip < HP-Fax4-hpcups.ppd.gz cat > ouT1?

    I'm not 100% sure how this is interpreted by all involved parties here, but let's speculate. The error is this:

    gzip: cat.gz: No such file or directory 

    The first word in this error is gzip, so we know gzip has run. Also we know (at least I do), that the redirections are set by the sell before the command is interpreted. So I analyse it this way:

    • < HP-Fax4-hpcups.ppd.gz - shell sets the process INPUT redirection to HP-Fax4-hpcups.ppd.gz, ie. the command to be executed will read from this file
    • > ouT1 - the OUTPUT of the command is to be redirected TO ouT1

    So far so good. What's left on the table now is this: gunzip cat. The standard interpretation of this is that gunzip is a command and cat is its argument. So now gunzip runs (with both IN and OUT redirections set), and it gets the string cat as its first argument. And somehow it throws the error:

    gzip: cat.gz: No such file or directory

    What does it mean, again? It's gzip saying that it can't find cat.gz. It wants to do something with it (most likely open it), and there's no such file or directory. Thus must be a matter of its internals why it makes cat.gz out of cat it got as an argument. A simple experiment reveals that it expects the argument to be in gzip format:

    $ echo asdf > cat.gz
    $ gunzip < in  cat >  ouT1
    gzip: cat.gz: not in gzip format

    The in file here is a simple text file, so hence the blank line, I gather.

You must log in to answer this question.

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