[gnu.bash.bug] File Name Globbing

bitbug@lonewolf.sun.com (James Buster) (07/15/89)

It seems what is desired is a variable that toggles globbing between one of
two behaviors:

The result of a globbing operation that fails causes the shell to return
the filename substitution pattern, rather than an error, if the pattern
is not matched, i.e.

sh> echo *.d
*.d
sh>

*or* a globbing operation that fails causes the shell to print a diagnostic
and stop processing the current command or script, i.e.

csh> echo *.d
echo: No match.
csh>

Being able to toggle this behavior is, I believe, a desirable thing.
The first style of behavior should probably be the default, but
for those who want the shell to warn them of errors, the second
could be done by setting a variable, such as `nomatch'. Note
that 4.3 csh uses the `nonomatch' variable to cause the first style
of behavior to occur.
--
--------------------------------------------
	     James Buster
	Mad Hacker Extraordinaire
	 bitbug@lonewolf.sun.com
	 sun.com!lonewolf!bitbug
--------------------------------------------

nickson@comp.vuw.ac.nz (Ray Nickson) (07/16/89)

   Date: 14 Jul 89 19:15:02 GMT
   From: bitbug@sun.COM
   Subject: File Name Globbing
   
   It seems what is desired is a variable that toggles globbing between one of
   two behaviors:
   
   The result of a globbing operation that fails causes the shell to return
   the filename substitution pattern, rather than an error, if the pattern
   is not matched, i.e.
   ...
   
   *or* a globbing operation that fails causes the shell to print a diagnostic
   and stop processing the current command or script, i.e.
   ...


All right, time for me to stick my neck out again.  The patch at the
end implements behaviour that is almost this; I despise csh's 
`No Match' whingeing so much that I refuse to make an empty glob an
error.  If this causes some scripts to hang reading stdin, then you
bought it, you pay for it.

This patch should be considered experimental; I don't intend to put it
into the installed bash here.  While I like the idea, I'm unhappy that
I had to change the globbing semantics to such an extent to make this
work comfortably; in particular, I've hacked gloobing so that the
first word of a command is _never_ globbed.  I can't think why anyone
would want the first word globbed, but still...  The reason I did this
was that `[' is a perfectly valid (and oft-used) command; perhaps the
best solution is to say that invalid (as opposed to empty) globbing
characters should be left as is.  Discussion?

Anyway, here's the patch; take it or leave it.  It gives current
behaviour when nullglobok is unset, and allows empty globs if it's
set.

-rgn
--
nickson@comp.vuw.ac.nz       ...!uunet!vuwcomp!nickson      + 64 4 721000x8593

PS: I intend to complete one more bash-hack, then revert to writing
my thesis for a week or so... :-)

--------------------cut here--------------------
*** subst.c.orig	Thu Jun 29 15:38:23 1989
--- subst.c	Sun Jul 16 13:47:59 1989
***************
*** 1227,1232 ****
--- 1227,1235 ----
    return (expand_words_1 (list, 0));
  }
  
+ /* do we accept null globs, or refuse to glob? */
+ int nullglobok = 0;
+ 
  /* The workhorse for expand_words () and expand_words_no_var ().
     First arg is LIST, a WORD_LIST of words.
     Second arg DO_VARS is non-zero if you want to do environment and
***************
*** 1315,1321 ****
      WORD_LIST *glob_list;
  
      orig_list = (WORD_LIST *)NULL;
!     tlist = new_list;
  
      if (!disallow_filename_globbing)
        {
--- 1318,1325 ----
      WORD_LIST *glob_list;
  
      orig_list = (WORD_LIST *)NULL;
!     tlist = new_list && nullglobok ? new_list->next : new_list;
!     /* nullglobok: chop off word 0 so it doesn't get globbed */
  
      if (!disallow_filename_globbing)
        {
***************
*** 1362,1369 ****
  	  
  		if (glob_list)
  		  orig_list = (WORD_LIST *)list_append (glob_list, orig_list);
! 		else
! 		  orig_list = make_word_list (copy_word (tlist->word), orig_list);
  	      }
  	    else
  	      {
--- 1366,1374 ----
  	  
  		if (glob_list)
  		  orig_list = (WORD_LIST *)list_append (glob_list, orig_list);
! 		else if (!nullglobok)
! 		  orig_list =
! 		    make_word_list (copy_word (tlist->word), orig_list);
  	      }
  	    else
  	      {
***************
*** 1379,1384 ****
--- 1384,1394 ----
  
  	    tlist = tlist->next;
  	  }
+ 	/* nullglobok: patch word 0 back on */
+ 	if (nullglobok)
+ 	  orig_list = (WORD_LIST *)
+ 	    list_append (orig_list,
+ 			 make_word_list (copy_word (new_list->word), 0));
  	dispose_words (new_list);
  	new_list = orig_list;
        }
***************
*** 1428,1434 ****
  /* Not really `extern' just `forward'. */
  extern int sv_path (), sv_mail (), sv_terminal (), sv_histsize (), sv_uids (),
    sv_ignoreeof (), sv_glob_dot_filenames (), sv_histchars (), sv_nolinks (),
!   sv_hostname_completion_file ();
  
  #ifndef NOJOBS
  extern int sv_notify ();
--- 1438,1444 ----
  /* Not really `extern' just `forward'. */
  extern int sv_path (), sv_mail (), sv_terminal (), sv_histsize (), sv_uids (),
    sv_ignoreeof (), sv_glob_dot_filenames (), sv_histchars (), sv_nolinks (),
!   sv_hostname_completion_file (), sv_nullglobok ();
  
  #ifndef NOJOBS
  extern int sv_notify ();
***************
*** 1456,1461 ****
--- 1466,1472 ----
    { "histchars", sv_histchars },
    { "nolinks", sv_nolinks },
    { "hostname_completion_file", sv_hostname_completion_file },
+   { "nullglobok", sv_nullglobok },
    { (char *)0x00, (Function *)0x00 }
  };
  
***************
*** 1475,1480 ****
--- 1486,1499 ----
  	}
        i++;
      }
+ }
+ 
+ /* what to do just after the nullglobok variable has changed */
+ sv_nullglobok ()
+ {
+   extern int nullglobok;
+   
+   nullglobok = (find_variable ("nullglobok") != 0);
  }
  
  /* What to do just after the PATH variable has changed. */

Ray Nickson <nickson@comp.vuw.ac.nz> (07/17/89)

   All right, time for me to stick my neck out again.  The patch at the
   end implements behaviour that is almost this; I despise csh's 
   `No Match' whining so much that I refuse to make an empty glob an
   error.  If this causes some scripts to hang reading stdin, then you
   bought it, you pay for it.

   This patch should be considered experimental; I don't intend to put it
   into the installed bash here.  While I like the idea, I'm unhappy that
   I had to change the globbing semantics to such an extent to make this
   work comfortably; in particular, I've hacked gloobing so that the
   first word of a command is _never_ globbed.  I can't think why anyone
   would want the first word globbed, but still...  The reason I did this
   was that `[' is a perfectly valid (and oft-used) command; perhaps the
   best solution is to say that invalid (as opposed to empty) globbing
   characters should be left as is.  Discussion?

1) Your patch closely matches mine, excepting two things.  The first is
   the name of the variable; I used "allow_null_glob_expansion".  The
   second is the excepting the first word of the command.  I didn't do
   this, mostly because it didn't occur to me.  But it brings up an
   interesting point.  You asked when someone would use globbing
   characters in a command.  The answer is: whenever they thought it
   would ease typing, just as in any other situation.  Perhaps the name
   of the command to run in the current directory is
   "please_run_this_command".  In that case, "ple*nd" will run that
   command, and will have saved the user much typing.

2) You say the reason that you didn't expand the first word is because
   you know of a command that contains a globbing character.  Well, this
   is a much better argument for Bourne shell behaviour than any other I
   have thought of, since the first word of a command is not the only
   place you will see a globbing character.  In the "if" command is
   another place.  As the second word in an "eval" command is another
   place.

Brian Fox

bart@videovax.tv.Tek.com (Bart Massey) (07/19/89)

In article <8907170737.AA04585@aurel.caltech.edu> bfox@aurel.caltech.edu.date.sun, 16 Jul 89 14:05:56 +1200 From: Ray Nickson <nickson@comp.vuw.ac.nz> writes:
>
> 2) You say the reason that you didn't expand the first word is because
>    you know of a command that contains a globbing character.  Well, this
>    is a much better argument for Bourne shell behaviour than any other I
>    have thought of, since the first word of a command is not the only
>    place you will see a globbing character.  In the "if" command is
>    another place.  As the second word in an "eval" command is another
>    place.

Agreed.  However, the earlier poster's suggestion that invalid globs not
expand should fix the problem.  E.g. '[a-z' is a literal string, but '[a-z]'
is a regexp.  Note that all such "invalid" cases must involve the characters
'[' or ']', since this is the only Bourne Shell globbing syntax which uses
more than one character.  Since '[' (a.k.a. 'set') is the only command I can
think of or find on my machine which even potentially causes globbing
problems, IMHO the above semantic should be more than adequate...

I have a piece of really slow, recursive match, Bourne Shell style globbing
code I wrote myself in C which implements the above semantic -- you're welcome
to it if you're interested.

					Bart Massey
					..tektronix!videovax.tv.tek.com!bart
					..tektronix!reed.bitnet!bart