[comp.unix.wizards] filename substitution question

gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/24/89)

In article <1627@ncar.ucar.edu> rob@scdpyr.ucar.edu (Robert Montgomery) writes:
>Often it would be simpler to specify what I *don't* want in filename
>substitution than what I do.  For example, I would like to do something
>similar the following:
>	ls {NOTfrog}.c
>and have it produce:
>	bird.c		fish.c

Unfortunately the shell's pattern expansion capabilities support only
a subset of the regular expression capabilities that you might expect
of a UNIX utility.  However, therein lies the clue: use some other
UNIX utility.  For example:
	ls `echo *.c|sed 's/frog.c/ /'`
Not as convenient as what you really want, but at least the capability
is available.

pete@escher.intel.com (Peter Johnson ~) (03/24/89)

In article <9911@smoke.BRL.MIL>, gwyn@smoke (Doug Gwyn ) writes:
>In article <1627@ncar.ucar.edu> rob@scdpyr.ucar.edu (Robert Montgomery) writes:
>>Often it would be simpler to specify what I *don't* want in filename
>>substitution than what I do.  For example, I would like to do something
>>similar the following:
>>	ls {NOTfrog}.c
>>and have it produce:
>>	bird.c		fish.c
>
>Unfortunately the shell's pattern expansion capabilities support only
>a subset of the regular expression capabilities that you might expect
>of a UNIX utility.  However, therein lies the clue: use some other
>UNIX utility.  For example:
>	ls `echo *.c|sed 's/frog.c/ /'`
>Not as convenient as what you really want, but at least the capability
>is available.

I use a program written by Chris tweed called "sets".  This program
just does set operations on its arguments.  So for example if you
wanted to remove all files except those that end in .c or .h you
can do something like this:

  rm `sets * -d *.c`

The -d stands for set difference.  Sets also supports intersection and union.

If you are interested, let me know and I will mail you a copy.

Peter Johnson

pete@escher.intel.COM
{amdcad,decwrl,hplabs,oliveb,pur-ee,qantel}!intelca!mipos3!pete

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (03/25/89)

Peter Johnson writes:
: I use a program written by Chris tweed called "sets".  This program
: just does set operations on its arguments.  So for example if you
: wanted to remove all files except those that end in .c or .h you
: can do something like this:
: 
:   rm `sets * -d *.c`
: 
: The -d stands for set difference.  Sets also supports intersection and union.
: 
: If you are interested, let me know and I will mail you a copy.

Just for the fun of it, here's about 1/2 hour's work in perl, one screenful.
I don't know if the tokenization or precedence is the same as the other
version, but this version of sets will do parens (the other one might too,
for all I know).  It's likely shorter.  And it would be trivial to add new
operators--one line apiece.

#!/usr/bin/perl
$setnum = 0;
$setstring = "\$set${setnum}_{\$_}";
while ($#ARGV >= 0) {
    $_ = shift;
    if (/^-[diu]$/) {
	++$setnum;
	$setstring = "\$set${setnum}_{\$_}";
	$expr .= '&&!'	if /^-d/;
	$expr .= '&&'	if /^-i/;
	$expr .= '||'	if /^-u/;
    }
    elsif (/^[()]$/) {
	$expr .= $_;
    }
    else {
	$universe{$_} = 1;
	$expr .= $setstring;  $setstring = '';
	eval "\$set${setnum}_{\$_} = 1;";
    }
}
eval "for (keys(universe)) { delete \$universe{\$_} unless $expr; }";
print join(' ',sort keys(universe)),"\n";

Larry Wall
lwall@jpl-devvax.jpl.nasa.gov

dgk@ulysses.homer.nj.att.com (David Korn[drew]) (03/25/89)

In article <9911@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
> In article <1627@ncar.ucar.edu> rob@scdpyr.ucar.edu (Robert Montgomery) writes:
> >Often it would be simpler to specify what I *don't* want in filename
> >substitution than what I do.  For example, I would like to do something
> >similar the following:
> >	ls {NOTfrog}.c
> >and have it produce:
> >	bird.c		fish.c
> 


ksh-88 has expanded the file matching capability to allow such matches.

The pattern !(frog) matches anything except frog, so that
ls !(frog)*.c matches any thing that ends in .c that does not
start with frog.  More commonly,
	ls !(*.o)
matches anything except *.o.  You can use | for alternation.
For example
	ls !(foo|bar)*.c
whill not match anything beginning with foo or bar.  The notation
	?(pattern-list) matches 0 or 1 or any pattern in list.
	+(pattern-list) matches 1 or more
	*(pattern-list) matches 0 or more of any pattern in list.

Of course these pattern can also be used with case statement and substrings.

scs@adam.pika.mit.edu (Steve Summit) (03/25/89)

In article <1627@ncar.ucar.edu> rob@scdpyr.ucar.edu (Robert Montgomery) writes:
>Often it would be simpler to specify what I *don't* want in filename
>substitution than what I do.  For example, I would like to do something
>similar the following:
>	ls {NOTfrog}.c
>and have it produce:
>	bird.c		fish.c

A nice solution which I have not seen mentioned yet is the "pick"
program, described in Kernighan and Pike's book, The Unix
Programming Environment.  You always invoke pick inside of
backquotes, viz.:

	command `pick *.c`

and you get to answer yes or no for each filename.  It'd be silly
for the ls example (but then again, so would anything; the
problem comes up more typically when the command in question is
going to modify the files somehow).

pick essentially allows you to add an "inquire" facility to any
program; for instance,

	rm -i *

is equivalent to

	rm `pick *`

The only problem with pick is that people who use the MH mail
system already have another meaning for the command.

For simply listing files, I find that postprocessing (rather than
preselecting) is usually more convenient.  For example, a
frequent idiom of mine is

	ls -lt | grep -v '\.o$'

to see what source files I've changed lately.

If you can neither find a copy of Kernighan and Pike (as I
recall, it included source code) nor write pick yourself (the
only tricky part is using /dev/tty) I can send you my
implementation. (I ought to just include it here; it's under 50
lines long.)

                                            Steve Summit
                                            scs@adam.pika.mit.edu

tr@madeleine.ctt.bellcore.com (tom reingold) (04/04/89)

On the subject of "filename substitution question", rob@scdpyr.ucar.edu
(Robert Montgomery) writes:

$ Often it would be simpler to specify what I *don't* want in filename
$ substitution than what I do.  For example, I would like to do something
$ similar the following:
$ 
$ 	ls {NOTfrog}.c
$ 
$ and have it produce:
$ 
$ 	bird.c		fish.c
$ 
$ Have I overlooked a "NOT"/"EXCEPT"/"EVERYTHING-BUT"-type special
$ character in the man pages?  Or is there another simple way to do this
$ simple action in Unix (e.g., sunOS 4.0 or BSD4.3)?

While everyone's solutions have been more elegant than mine, I think
I should post the most obvious one.

	ls | grep -v frog.c

(And it was quite a coincidence that David Korn mention the new feature
of ksh's regular expressions.  I read the article yesterday morning and
wished we could get the new ksh.  Then it arrived last night.)

Tom Reingold                   |INTERNET:       tr@ctt.bellcore.com
Bell Communications Research   |UUCP:           bellcore!ctt!tr
444 Hoes La room 1E225         |PHONE:          (201) 699-7058 [work],
Piscataway, NJ 08854           |                (201) 287-2345 [home]

friedl@vsi.COM (Stephen J. Friedl) (04/05/89)

[ how do we list all files *except* mentioned ones? ]

In article <15131@bellcore.bellcore.com>, tr@madeleine.ctt.bellcore.com (tom reingold) writes:
> While everyone's solutions have been more elegant than mine, I think
> I should post the most obvious one.
> 
> 	ls | grep -v frog.c
> 

Be careful here.  Many versions of ls columnize their output, so
the above will exclude everything that appears on the same line
as the mentioned file.  This can happen either by ls's default action
or by aliases or shell functions defined by {/etc/,.}profile.

     Steve

-- 
Stephen J. Friedl / V-Systems, Inc. / Santa Ana, CA / +1 714 545 6442 
3B2-kind-of-guy   / friedl@vsi.com  / {attmail, uunet, etc}!vsi!friedl

"I do everything in software, even DMA" - Gary W. Keefe (garyk@telxon)

gwyn@smoke.BRL.MIL (Doug Gwyn ) (04/06/89)

In article <1083@vsi.COM> friedl@vsi.COM (Stephen J. Friedl) writes:
>> 	ls | grep -v frog.c
>Be careful here.  Many versions of ls columnize their output, ...

But not when their standard output is other than a terminal (!isatty(1)).