Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!sri-unix!quintus!ok From: ok@quintus.UUCP (Richard A. O'Keefe) Newsgroups: comp.unix.wizards Subject: Re: Command interfaces Message-ID: <450@cresswell.quintus.UUCP> Date: Tue, 8-Dec-87 21:45:29 EST Article-I.D.: cresswel.450 Posted: Tue Dec 8 21:45:29 1987 Date-Received: Sun, 13-Dec-87 16:29:31 EST References: <1257@boulder.Colorado.EDU> <6840002@hpcllmv.HP.COM> <9555@mimsy.UUCP> <17130@bu-cs.BU.EDU> Organization: Quintus Computer Systems, Mountain View, CA Lines: 79 Summary: wild-carding with sed(1) and xargs(1) In article <17130@bu-cs.BU.EDU>, budd@bu-cs.BU.EDU (Philip Budne) writes: > Many TOPS-10 utilities (including PIP) had > powerful wild-card abilities; > .RENAME FOO*.X=BAR*.Y > Neither TOPS-20 nor Un*x can do this as simply. Someone commenting favourably on a version of PR1MOS more recent than the one I used 5 years ago mentioned that PR1MOS has a similar feature. This is DEFINITELY not one for the novices! Let's suppose we have a uniform system so that every command that does this at all does it the same way, and those that don't report it as an error. Quickly now, what does RENAME NEW*FOO?.TXT AS OLD?FOO*.TXT do? What happens if there are different numbers of wild-cards in the two sides? For example, suppose you have a "MOVETO " command, then MOVE NEW*FOO*.TXT TO NEWFOO* might be a reasonable thing to do, if only you knew what it meant. What happens if you want to say "remove each *.o for which the corresponding *.c or *.s exists?" I have used operating systems with this sort of feature, and the trouble was that except in the very simplest case (exactly one wild-card in both patterns, and it is the same wild-card in both places) I never quite knew what it was going to do. If what you want to do fits into the strait- jacket the command-line-processor's designer happened to think of, fine. If you want anything slightly more complicated, you are just as much on your own as you are in the Bourne shell. What we want is a general way of mapping file-names from one form to another. What's a good tool for that? Why, an editor! The Bourne shell equivalent of the rename thingy is ls | sed -n -e 's^/foo\(.*\).x$/& baz\1.y/p' | xargs -n2 mv -------------------###########----#######----------------## The underlined characters are boiler-plate. The first chunk of sharps marks the pattern to match the old name. The second chunk of sharps marks the pattern to generate the old and new names together. The last chunk of sharps marks the command you want applied. If you add '-p' just after "xargs", you will be prompted for permission to execute each constructed command. This makes ANY command interactive. The scheme generalises to making any number of new file names, and lets you permute the chunks matched by the wild-cards any way you like. If you haven't got xargs, or if you don't trust the one you've got, you can change the sed script slightly and pipe it into the shell: ls | sed -n -e 's^/foo\(.*\).x$/mv & baz\1.y/p' | sh -f -------------------###########--##---#######----------- The "-f" here suppresses file-name expansion in the shell. You can insert "pick" as another pipe-line stage to make it interactive. Neither version of this pipeline is particularly simple, and I agree that this is not the kind of thing you want to type in. On the other hand, I have never done RENAME FOO*.X BAZ*.Y that I didn't end up regretting it. It is not clear to me that making a hard-to-understand command easy to type is a great virtue. This pipeline IS, however, the kind of thing you might reasonably put in a script. Whenever I have wanted to do something like this, I have first wanted to check that it was going to do what I expected it to, and often there isn't any way of doing so (perhaps the current PR1MOS equivalent of "echo", whatever that is?). On a BSD system, I can type ls | sed -n -e and check what comes out the other end, and when I am confident that I have the transformation right I can then say !! | xargs -p -n2 mv This touches on a user interface topic that I haven't seen mentioned yet, which is that when I am about to do something complicated I like to build the command up in small steps, testing it as I go. I was about to say that this is orthogonal to the globbing in the shell/in the command question, but in fact it ISN'T. Because what I want is to be able to see exactly what command will be executed and with exactly which arguments, *without* actually running the command. (In fact, at the time I test the script, the command may well not be written yet.) If you never write anything complicated enough to warrant testing, globbing in the command may be just what you want, but the chances are the Macintosh interface would suit your needs even better.