[comp.unix.wizards] Avoiding shell for loops

gilles@chorus.fr (Gilles Courcoux) (06/13/90)

In article <3133@goanna.cs.rmit.oz.au>, ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
> 
> 	#!/bin/sh
> 	#   change "FromPattern" "ToPattern" File...
> 	#   see sed(1) for an explanation of patterns
> 	From="$1"
> 	shift
> 	To="$1"
> 	shift
> 	for File
> 	    do
> 		mv "$File" "`echo "$File" | sed -e "s/$From/$To/"`"
> 	    done
> 	exit

Just to say, there is one general improvement that can be used
on this type of code: don't use any loop at all!
Just build your commands with sed(1), then pipe them through the shell.

Doing so, you reduce the number of processes to fork (3 per file vs. 4),
and because `for' loops are very slow you get the whole job be
done faster.

      #!/bin/sh
      #   change "FromPattern" "ToPattern" File...
      #   see sed(1) for an explanation of patterns
      From="$1"
      shift
      To="$1"
      shift
      echo $* \
      | tr ' ' '\012' \
      | sed \
	-e "/$From/!d" \
	-e "s/$From/$To/" \
	-e 's/.*/mv & &/' \
	-e "s/$To/$From/" \
      | sh

The tr(1) command is just there to build an input stream of
one word per line for sed.

Note that you can say
	$ change .c .pouet *
because files not concerned by the move won't be moved (first line
of the sed script).

Gilles
--
Gilles Courcoux
Chorus systemes                          E-mail: gilles@chorus.fr
6 avenue Gustave Eiffel                  Phone: +33 (1) 30 57 00 22
F-78182, St-Quentin-en-Yvelines-Cedex    Fax: +33 (1) 30 57 00 66