[sf-lug] Nope, and nope: Re: > and >> and < and << and |

jim jim at well.com
Mon Aug 8 22:41:15 PDT 2016


(great!)
     Terrific counter example; it's truly exotic, but
it sure makes the point.

     Now my interpretation is that the  >  character
is an operator that takes a subsequent operand, which
must be a file name, kind of like the  >  operation
is running in a sub-shell, or maybe kind of like
word expansion as the shell parses the command line
fields, e.g.
$ ... $SHELL ....

     I want to walk through my newly qualified
understanding (I just perused the  dash  man page).

     The token (string) to the right of the  >
character (operator) must be a valid file
specification. If there is any text string token
to the right of the  >  character, the shell
treats it as a file specification.
$ echo a b c > d e f
$ ls
d
$ cat d
a b c e f
$
     The shell blindly passes the text string
(in the above case, d ) to the kernel as part
of the system call to open a file (and return
the inode number and set the file pointer to
the first byte in the file).

     And there's this case
$ > g
$ ls
g
$ cat g
$
     I guess it's an alternative to the  touch
command for creating an empty file.

$ echo $EMPTY  ## no such envvar hence no value
$ > $EMPTY
dash: 23: cannot create : Directory nonexistent
$ > $EMPTY /proc/abc
dash: 23: cannot create : Directory nonexistent
$ /proc/abc > $EMPTY
dash: 25: cannot create : Directory nonexistent
$ echo "boom" > $EMPTY
dash: 26: cannot create : Directory nonexistent
$ > $EMPTY
dash: 27: cannot create : Directory nonexistent
$ > $EMPTY
dash: 28: cannot create : Directory nonexistent
$ > $EMPTY
dash: 29: cannot create : Directory nonexistent
$ echo "blast" > $EMPTY
dash: 30: cannot create : Directory nonexistent
$ /proc/abc
dash: 31: /proc/abc: not found
$ >
dash: 32: Syntax error: newline unexpected

     What's with the incrementing numbers? I'm
guessing it's a history number for each command.
     Per above, in every case that there's more
than just the redirection operation, the shell
first performs the redirection operation and if
that fails, the shell does not try anything else
on that lime, somewhat similar to using
the  &&  operator.



On 08/09/2016 03:54 AM, Michael Paoli wrote:
> Nope and nope.
>
> I'll disprove your conjectures by counter-example.
>
>> From: jim <jim at well.com>
>> Subject: Re: [sf-lug] > and >> and < and << and |
>> Date: Mon, 8 Aug 2016 17:32:53 +0000
>
>>     What  >  tells the shell is that the stuff
>> to the left is a complete command and the
>
> Your conjecture has two false items in it.
> You state in your conjecture:
> ">  tells the shell is that the stuff to the left is a complete command"
>
> That's false in two parts:
>
> That it (>) tells the shell it is a complete command.
>
> That what is a complete command, is that to the left of it (>).
>
> Both of those statements are false.
>
> Here are counterexamples to prove they're false - actually even
> a single counterexample proving the falsity of both at the same time:
> $ ls
> $ echo a b c >out d e f
> $ cat out
> a b c d e f
> $
> We can see in the above, that the command is not terminated at all by >,
> but rather that >out merely redirects stdout to our file called out.
> the d e and f arguments continue to be arguments to the echo command,
> hence they, along with the preceding a b c arguments, end up in the
> file to which we redirected stdout.  If > told the shell that what was to
> the left was a complete command, how, pray tell, would you explain the
> d e and f ending up in that out file that we created?
> And that the command is to the left?  Again, then how did the d e and f
> to the right get in that output file?
> Yes, typically redirection would be at start or end of the command,
> but it needn't be.  Read the documentation - notably the man pages - 
> though
> examples may show it on left or right, there's nothing that states that's
> where it must be, and in fact, those redirections can occur most 
> anywhere on
> the command line.  There are, however, some caveats - redirection is
> processed left to right, so these generally are not the same:
>> out 2>&1 some_command
> 2>&1 >out some_command
> however these are all equivalent:
>> out 2>&1 some_command
>> out some_command 2>&1
> some_command >out 2>&1
> Note however | is a bit different in that regard,
> as the command preceding it is piped to the
> command following it.
> Here's another example:
> $ ls
> $ >foo echo foo
> $ cat foo
> foo
> $
> Oh what, pray tell, would be the command to the left of > that would
> explain how foo ended up in our file named foo?
>
> Sorry if I may confuse the matter with facts.  ;->
>
>> On 08/08/2016 03:00 PM, Michael Paoli wrote:
>>>> different command. (The shell has other
>>>> command-line termination characters, such
>>>> as > and >> and < and << and | and more.)
>>>
>>> Actually, > and >> and < and << and | aren't shell termination
>>> characters, but rather various forms of redirection.
>>> The last of those (|) forming a pipeline - which is a form
>>> of more complex command/list, whereas the others are used for generally
>>> simpler redirection.  Shell termination characters are semi-colon (;)
>>> and newline (typically stty settings will map carriage return of
>>> keyboard input to newline).
>>>
>>> Example:
>>> $ >out echo output
>>> $ cat out
>>> output
>>> $
>>> We can see quite clearly in the above, the > did not terminate our 
>>> shell
>>> command at all, but rather was used to redirect standard output of our
>>> echo command to a file we named out.
>>>
>>> Can also add newlines while typing the echo command on a single line,
>>> e.g.:
>>> $ cat out && echo -e '\n\n'
>>> output
>>>
>>>
>>>
>>> $
>>> I'll leave explaining the details of the above as an exercise. :-)
>>>
>>>> From: jim <jim at well.com>
>>>> Subject: [sf-lug] dumb little command-line trick
>>>> Date: Mon, 8 Aug 2016 05:15:08 +0000
>>>
>>>>
>>>> (optional reading)
>>>>    (I used to teach intro programming classes
>>>> and miss it.) This is for people getting
>>>> started using the command-line.
>>>> ------------------------------------------------
>>>>    Some command-line users I admire issue
>>>> a command, watch its output, and then hit
>>>> the  Enter  key a few times to create some
>>>> blank lines that make some space between
>>>> the output of the command and the command
>>>> that they next invoke:
>>>>
>>>> $ doit
>>>> this and that and more
>>>> $
>>>> $
>>>> $
>>>> $ icommandyou be good
>>>> gurgle burble
>>>>
>>>>    I invoke the  doit  command, which prints
>>>> its output (this and that and more) then I hit
>>>> the  Enter  key three times and then invoke
>>>> the  icommandyou be good  command, which
>>>> prints its output (gurgle burble). I review
>>>> what I've done and have convenient blank lines
>>>> separating the two different commands and their
>>>> outputs.
>>>>
>>>>
>>>>    My dumb little trick is similar, but I use
>>>> the  echo  command and the  ;  (semi-colon)
>>>> command-separation character and then the command
>>>> I want to run.
>>>>
>>>> $ echo "
>>>>
>>>>
>>>> " ; doit
>>>>
>>>>
>>>>
>>>> this and that and more
>>>> $
>>>>
>>>>    For those interested, my trick has three parts,
>>>>
>>>> echo "
>>>>
>>>>
>>>> "
>>>> ## what this does it to print three blank lines
>>>> to the display.
>>>>
>>>> as well as
>>>>
>>>> ;
>>>> ## what this does is to tell the shell that
>>>> everything to the left is a command and
>>>> everything to the right is a completely
>>>> different command. (The shell has other
>>>> command-line termination characters, such
>>>> as > and >> and < and << and | and more.)
>>>>
>>>> doit
>>>> ## this is the command I want to run.
>>>>
>>>>    My dumb little command-line trick lets me
>>>> run a command but issue a few blank lines
>>>> before the command runs, so I get a little
>>>> blank space above the output of the command.
>>>>
>>>>    I can make a shell script that saves a
>>>> little time and possible typing errors.
>>>>
>>>> $ pwd
>>>> /home/jim/bin  ## here's my current directory
>>>> $ echo $PATH
>>>> /home/jim/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
>>>> ## I set my PATH environment variable to include my
>>>> own  bin  directory, /home/jim/bin
>>>>
>>>> $ vi blns
>>>> echo "
>>>>
>>>>
>>>> "
>>>> $ chmod 755 blns
>>>>
>>>>    Now I can use my dumb little trick like this
>>>>
>>>> $ blns ; doit
>>>>
>>>> ## I suppose I could have put the  ;  command
>>>> ## separation character in the shell script,
>>>> ## but for some reason I feel better making
>>>> ## myself type that character
>>>>
>>>> ## I made up the name  blns  to suggest "blank lines".
>
>
> _______________________________________________
> sf-lug mailing list
> sf-lug at linuxmafia.com
> http://linuxmafia.com/mailman/listinfo/sf-lug
> Information about SF-LUG is at http://www.sf-lug.org/
>





More information about the sf-lug mailing list