[comp.unix.shell] How to do mv *.xyz *.abc in shell script??

rcoahk@chudich.co.rmit.oz (Alvaro Hui Kau) (09/07/90)

Hi all experts out here!

Sorry for the stupid query, but I just don't know how to do
it. Once in a while I want to change the names of a bunch of
files from *.xyz to *.abc for example. I know there is a better
way to do this than doing it one by one but I just can't
find any way to do it. I know it can be done using shell script
but I don't know (yet) how to write them.

So, Is there anyone out there can help me on this problem?

Thanks in advance.

===============================================================================
	Alvaro Hui		|ACSnet		akkh@mullian.oz
    4th Year B.E.\ B.Sc.	|Internet &	akkh@mullian.ee.mu.OZ.AU
   University of Melbourne	|Arpanet	rcoahk@koel.co.rmit.OZ.AU 

lrb@rrivax.rri.uwo.ca (Lance R. Bailey) (09/07/90)

In article <5569@minyos.xx.rmit.oz>, rcoahk@chudich.co.rmit.oz (Alvaro Hui Kau) writes...
>So, Is there anyone out there can help me on this problem?

# changing *foo to *bar
for i in *foo
do
    j=`echo $i | sed -e 's/foo/bar/'`
    mv $i $j
done
_________________________________
Lance R. Bailey, Systems Manager | Robarts Research Institute
email: lrb@rri.uwo.ca            | Clinical Trials Resources Group
  vox: 519-663-3787 ext. 4108    | P.O. Box 5015, 100 Perth Dr.
  fax: 519-663-3789              | London, Canada N6A 5K8

de5@de5.CTD.ORNL.GOV (Dave Sill) (09/07/90)

I picked this up on comp.unix.wizards a few years back.  Typical uses:

mved lib=.a =.a		moves   libhello.a to hello.a
mved =.o =.o.old	moves	fred.o to fred.o.old
mved '=.*' =		moves	fred.junk to fred
mved =.sh =		moves	mved.sh to mved
mved *.sh =.

#! /bin/sh
# mved.sh
# Move-and-edit filenames.
#
#	Usage: mved [-n] from-pattern to-pattern
#
#	This command allows you to change file names much as is possible
#	with some versions of PIP (remember *.txt=*.bak?).
#	The '=' character in from-pattern is treated as a special wildcard,
#	matching in the same way as the shell '*' wildcard character, except
#	that the text matching the '=' in the first pattern is inserted in
#	place of any = wildcards in the second.
#	Note that from-pattern need not have a wildcard if to-pattern does,
#	a default 
#
#	Use the '-n' option to do nothing, showing what would be done.
#
#	Restrictions:
#	Only the first '=' sign in from-pattern is used.  Multiple =
#	wildcards in from-pattern match up with the first from-pattern
#	=, ie: there is no matching for multiple = signs.  (I'm sure
#	someone could make it work if they wanted to... ?)
#
#   eg: mved lib=.a =.a		moves   libhello.a to hello.a
#	mved =.o =.o.old		moves	fred.o to fred.o.old
#	mved '=.*' =		moves	fred.junk to fred
#	mved =.sh =		moves	mved.sh to mved
#	mved *.sh =.
#
#			Brian Coogan 06 Jan 87
#			Hewlett-Packard Australian Software Operation
# $Header$ ASO

shopt=x
case "$1" in
-n)	shopt=vn; shift ;;
esac

# Check for appropriate wildcards.
# Source must have an = or a * wildcard or already exist.
case "$1" in
*=*)	;;
*)	for n in $1
	do if [ ! -f "$n" ]
	then
		echo "$0: No files match from-pattern!\n" 1>&2
		set -- "$@" give usage message
	elif [ "$2" = '=' ]
	then
		echo Nothing doing.
		exit 0
	fi
	break
	done
	;;
esac
case "$2" in
*=*)	;;
*)	echo "$0: No '=' wildcards used in target!\n" 1>&2
	set -- "$@" give usage message
	;;
esac
# catch mved = =
case "$1$2" in
==)	echo Nothing doing.; exit 0;;
esac



if [ $# -ne 2 ]
then
	echo "Usage: $0 [-n] from-pattern to-pattern" 1>&2
	echo "\tEquals (=) signs in the to-pattern match like '*' and are"
	echo "\treplaced with the text that matched the = in from-pattern."
	echo "\tYou must quote any '*'s in from-pattern."
	exit 1
fi

globpatt=`echo $1 | sed 's/=/\*/'`

frompatt=`echo "$1" | sed \
			-e 's/\./\\\\./g' \
			-e 's/\*/.*/g' \
			-e 's/=/\\\\(\\.\\*\\\\)/' \
			-e '/\\\\(/ !s/.*/\\\\(&\\\\)/'
			`
topatt=`echo "$2" | sed -e 's/=/\\\\1/g'`


for n in $globpatt
do
	# Check the pattern got expanded.  (The file might also have vanished).
	if [ ! -f $n ]
	then
		echo "$0: No files matching $1 found." 1>&2
		exit 1
	fi
	echo $n
done |
sed -n "s;$frompatt;mv & $topatt;p" | sh -$shopt

echo done

-- 
Dave Sill (de5@ornl.gov)		These are my opinions.
Martin Marietta Energy Systems
Workstation Support

lrb@rrivax.rri.uwo.ca (Lance R. Bailey) (09/07/90)

In article <975@ria.ccs.uwo.ca>, lrb@rrivax.rri.uwo.ca (Lance R. Bailey) writes...
> 
># changing *foo to *bar
>for i in *foo
>do
>    j=`echo $i | sed -e 's/foo/bar/'`
should read
     j=`echo $i | sed -e 's/foo$/bar/'`
                               ^<---missing dollar sign to bind to end of string
>    mv $i $j
>done
_________________________________
Lance R. Bailey, Systems Manager | Robarts Research Institute
email: lrb@rri.uwo.ca            | Clinical Trials Resources Group
  vox: 519-663-3787 ext. 4108    | P.O. Box 5015, 100 Perth Dr.
  fax: 519-663-3789              | London, Canada N6A 5K8

mcdaniel@adi.com (Tim McDaniel) (09/07/90)

This is from Dan LaLiberte of the University of Illinois at
Urbana-Champaign.  I've used it for years.  The conversion to
Bourne-shell syntax should be obvious.  Usage is like
	rename 's/\.xyz$/abc/' *.xyz

#! /bin/csh -f
#/* Written  7:36 pm  May 29, 1988 by liberte@uiucdcsm.cs.uiuc.edu in
# uicsrd.csrd.uiuc.edu:comp.sources.d */
# Here is my rename script.
#
# Dan LaLiberte
# liberte@a.cs.uiuc.edu
# uiucdcs!liberte
#
# ---
#
# rename files with a sed command.  File names may have spaces in them.

if ($#argv < 2) then
	echo "Usage: rename sed-command file ..."
	exit (1)
endif
set command = "$1"
shift
set noglob
while ($#argv > 0)
	set name = ($argv[1])
	shift
	set newname = `echo "$name" | sed -e "$command"`
	if ($status != 0) exit 1
	echo "mv -i $name $newname"
	mv -i "$name" "$newname"
end
exit 0

# /* End of text from uicsrd.csrd.uiuc.edu:comp.sources.d */
--
Tim McDaniel                 Applied Dynamics Int'l.; Ann Arbor, Michigan, USA
Work phone: +313 973 1300                            Home phone: +313 677 4386
Internet: mcdaniel@adi.com                UUCP: {uunet,sharkey}!amara!mcdaniel

molenda@msi.umn.edu (Jason Molenda) (09/07/90)

lrb@rrivax.rri.uwo.ca (Lance R. Bailey) writes:

>In article <5569@minyos.xx.rmit.oz>, rcoahk@chudich.co.rmit.oz (Alvaro Hui Kau) writes...
>>So, Is there anyone out there can help me on this problem?

># changing *foo to *bar
>for i in *foo
>do
>    j=`echo $i | sed -e 's/foo/bar/'`
>    mv $i $j

in csh it's even easier

foreach i ( *foo ) 
   mv $i {$i:r}.bar
end

Jason Molenda, Tech Support, Iris & News admin, Minnesota Supercomputer Inst
molenda@s1.msi.umn.edu

tchrist@convex.COM (Tom Christiansen) (09/07/90)

I still like this one (from the FAQ):

    #!/usr/bin/perl
    #
    # rename script examples from lwall:
    #	rename 's/\.orig$//' *.orig
    #	rename 'y/A-Z/a-z/ unless /^Make/' *
    #	rename '$_ .= ".bad"' *.f
    #	rename 'print "$_: "; s/foo/bar/ if <stdin> =~ /^y/i' *

    $op = shift;
    for (@ARGV) {
	$was = $_;
	eval $op;
	die $@ if $@;
	(rename($was,$_) || warn "$0: can't rename $was to $_: $!\n")
	    if $was ne $_;
    }

--
 "UNIX was never designed to keep people from doing stupid things, because 
  that policy would also keep them from doing clever things." [Doug Gwyn]

lmiller@aerospace.aero.org (Lawrence H. Miller) (09/07/90)

One way to do this is to use basename.  Try something like this (for
you specific case of changing *.xyz to *.abc).

(This is a Bourne shell script.)

------------------------------ CUT HERE ------------------------------ 

for i in *.xyz
do
  a=`basename $i .xyz`
  echo moving $a.xyz to $a.abc
  mv $a.xyz $a.abc
done

Larry Miller
Aerospace Corporation
lmiller@aerospace.aero.org
213-336-5597

chet@cwns1.CWRU.EDU (Chet Ramey) (09/08/90)

changing *foo to *bar

>in csh it's even easier
>
>foreach i ( *foo ) 
>   mv $i {$i:r}.bar
>end

In bash or ksh, it's just as easy:

cwns1$ ls
1.foo   2.foo   3.foo   4.foo   5.foo   6.foo   7.foo   8.foo   9.foo
cwns1$ for i in *.foo
> do
> mv $i ${i%.*}.bar
> done
cwns1$ ls
1.bar   2.bar   3.bar   4.bar   5.bar   6.bar   7.bar   8.bar   9.bar

Chet
-- 
Chet Ramey				``Levi Stubbs' tears run down
Network Services Group			  his face...''
Case Western Reserve University	
chet@ins.CWRU.Edu		

hunt@dg-rtp.dg.com (Greg Hunt) (09/08/90)

In article <5569@minyos.xx.rmit.oz>, rcoahk@chudich.co.rmit.oz (Alvaro Hui Kau) writes:
> Hi all experts out here!
> 
> Sorry for the stupid query, but I just don't know how to do
> it. Once in a while I want to change the names of a bunch of
> files from *.xyz to *.abc for example. I know there is a better
> way to do this than doing it one by one but I just can't
> find any way to do it. I know it can be done using shell script
> but I don't know (yet) how to write them.
> 
> So, Is there anyone out there can help me on this problem?
> 
> Thanks in advance.
>

There are no stupid questions.  Just ones you don't know the answers
to yet.  This is how I change the names of files like you need to in
the Bourne shell:

    for tmp in $* ; do
        mv $tmp `basename $tmp .xyz`.abc
    done

The basename program returns just the file name portion of a pathname,
and optionally removes a suffix.  Since there is no pathname portion
if you're in the directory the files exist in, all that this example
does is to remove the suffix.  Then it puts on the new suffix, and
the files get renamed the way you want.

Put the above lines into a file named whatever you want with an editor.
Exit the editor.  Then type 'chmod 755 your_script_name'.  This changes
the file permissions to user{read,write,execute}, group{read,execute},
other{read,execute}.  The "execute" permission is the key to being able
to run shell scripts.  To use the script, type:

    your_script_name *.xyz

As you learn more about scripts, you can make it more general by
allowing you to specify the old and new suffixes as arguments to the
script as well (hint - look at the shift shell command and specify the
old and new suffixes as the first two arguments).

Enjoy!

--
Greg Hunt                        Internet: hunt@dg-rtp.dg.com
DG/UX Kernel Development         UUCP:     {world}!mcnc!rti!dg-rtp!hunt
Data General Corporation
Research Triangle Park, NC       These opinions are mine, not DG's.

keith@sequoia.execu.com (Keith Pyle) (09/08/90)

OK, so it's not done with the shell, but the program mmv posted to
comp.sources.unix (Volume 21, Issue 87) does this and a good deal more.
With mmv, the method would be:

mmv '*.xyz' '=1.abc'

Here's a bit of the man page:

NAME
     mmv - move/copy/append/link multiple files by wildcard  pat-
     terns

SYNOPSIS
     mmv [-m|x|r|c|o|a|l|s] [-h] [-d|p] [-g|t] [-v|n] [from to]

DESCRIPTION
     Mmv moves (or copies, appends, or links, as specified)  each
     source  file  matching  a  from  pattern  to the target name
     specified by the to pattern.  This multiple action  is  per-
     formed safely, i.e. without any unexpected deletion of files
     due to collisions of target names with existing filenames or
     with  other  target  names.   Furthermore, before doing any-
     thing, mmv attempts to detect any errors that  would  result
     from  the entire set of actions specified and gives the user
     the choice of either proceeding by  avoiding  the  offending
     parts or aborting.
-- 
-----------------------------------------------------------------------------
Keith Pyle                                UUCP: ...!cs.utexas.edu!execu!keith
Execucom Systems Corp., Austin, Texas     Internet: keith@execu.com
"It's 10 o'clock.  Do you know where      Disclaimer: What??
   your child processes are?"                  You actually believed me?
-----------------------------------------------------------------------------

jimr@hp-lsd.COS.HP.COM (Jim Rogers) (09/11/90)

Following is a ksh script which I find useful for this purpose:


#!/bin/ksh

# This script changes the ending patterns in a set of files.
# The pattern to look for  is described as the argument to the "-f"
# option.  The pattern to create is described as the argument to the "-t"
# option.  The script will work on the list of file names following the
# options.

set -- `getopt f:t: $*`
if [ $? -ne 0 ]
then
	print -u2 "Usage: $0: -f current_pattern -t new_pattern file ..."
	exit 1
fi

old=""
new=""

for opt in $*
do
	case $opt in
		-f)	old="$2"; shift 2;;
		-t)	new="$2"; shift 2;;
		--)	shift; break ;;
	esac
done
if [ "$old" = "" ]
then
	print -u2 "Error $0: Must specify an ending pattern to change."
	exit 2
fi
for file in $*
do
	prefix=${file%$old}
	if [ "$prefix" != "$file" ]
	then
		newfile="$prefix""$new"
		mv "$file" "$newfile"
	fi
done



-------------------------------------------------------------------------------
Jim Rogers
Logic Systems Division
Hewlett Packard Company

jonu@FtCollins.NCR.com (Jon Udell) (09/14/90)

In article <5569@minyos.xx.rmit.oz> rcoahk@chudich.co.rmit.oz (Alvaro Hui Kau) writes:


> Once in a while I want to change the names of a bunch of
> files from *.xyz to *.abc for example.


I use 

   mkcmd "mv *.xyz #.xyz" | /bin/csh -f



Our man page for mkcmd states it is from Sun Release 3.4.

--
------------------------------------------------------------------------------
Jon Udell
NCR Microelectronics Products Division      Jon.Udell@FtCollins.NCR.COM   
2057 Vermont                                uunet!ncrlnk!ncr-mpd!ncr-fc!jonu
Fort Collins, CO 80525                      (303) 223-5100 X431 
-------------------------------------------------------------------------------

guy@auspex.auspex.com (Guy Harris) (09/16/90)

>Our man page for mkcmd states it is from Sun Release 3.4.

I find this difficult to believe; I don't remember it being there when I
was at Sun and using SunOS 3.x, and it ain't in SunOS 4.0.3.

Does it *explicitly* say it came from there, or is it just that the page
footers on the manual page say "Sun Release 3.4"?  The latter doesn't
mean the program in question necessarily came from there; it just means
the manual page was *formatted* on a SunOS 3.4 system.