[net.sources] rename

ggc@myrias.UUCP (02/27/87)

I wrote this program one day when I got tired of writing the
familliar 4 line shell script for the 97'th time that week.
See the README and rename.l files for all the directions.

				Gilles
				...!ihnp4!myrias!ggc

===================CUT HERE==================================
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	rename.c
#	Makefile
#	rename.l
#	README
# This archive created: Thu Feb 26 14:15:16 1987
export PATH; PATH=/bin:$PATH
echo shar: extracting "'rename.c'" '(5547 characters)'
if test -f 'rename.c'
then
	echo shar: will not over-write existing file "'rename.c'"
else
cat << \SHAR_EOF > 'rename.c'
/*
 Project:	rename
 Module:	main
 File:		rename.c	$Revision$
 Synopsis:	rename [-i] file [...] [prefix]^=[suffix]
 Option:
	-i : interactive mode.  Query before erasing a file
 Machine:	vax 780
 Author: Gilles Chartrand
 Purpose:
	Rename many files by adding a suffix and/or prefix to each.

 Date:	Jan. 1986
*/

#include <stdio.h>
#include <strings.h>
#include <sys/file.h>

#define XBREAK	'^'
#define RBREAK	'='
#define MAX_LEN	40
#define ERROR(me)	fprintf(stderr, "%s\n", me) ;

typedef	enum {unknown, expand, replace} op_type_t ;
typedef enum {false, true} bool_t ;

extern int	rename() ;	/* libc function to rname files */
static void	multi_exp() ;	/* expand file names */
static void	multi_rep() ;	/* replace substring in file */
static void	my_rename() ;
static char	*sindex() ;	/* find a substring in a string */

bool_t		i_flag ;

void
main(argc, argv)
char	*argv[] ;
int	argc ;
{
	char		*str1, *str2, *scan ;
	op_type_t	op_type ;

	if (strcmp(argv[1], "-i") == 0) {
	    i_flag = true ;
	    argv ++ ;
	    argc -- ;
	}

	if (argc < 3) {
	    ERROR("usage: rename [-i] file [...] [str1]<^|=>[str2]") ;
	    exit(1) ;
	}

	str1 = "" ;
	str2 = "" ;
	op_type = unknown ;

	scan = argv[argc - 1] ;
	if (scan[0] == XBREAK) {
	    op_type = expand ;
	    str2 = scan + 1 ;

	} else {

	    str1 = scan ;
	    while (*scan != '\0' && *scan != XBREAK && *scan != RBREAK) scan++ ;
	    if (*scan == '\0') {
		ERROR("rename: a ^ or a = must appear in the last argument");
		exit(1) ;
	    }
	    str2 = scan + 1 ;
	    if (*scan == XBREAK)	op_type = expand ;
	    else			op_type = replace ;

	    *scan = '\0' ;
	}

	if ((strlen(str1) + strlen(str2)) == 0) {
	    ERROR("rename: one of str1 or str2 must be given") ;
	    exit(1) ;
	}

	if (op_type == expand)	multi_exp(argv + 1, argc - 2, str1, str2) ;
	else			multi_rep(argv + 1, argc - 2, str1, str2) ;
} /* main */

/*
 Procedure: multi_exp(file_array, count, prefix, suffix)
 Parameters:
	file_array : array of files to be moved.
	count : number of files in above array.
	prefix : prefix to add to the front of the file.
	suffix : suffix to add to the front of the file.
 Description:
	Expand each of the given files to have the given prefix and suffix.
*/
static void
multi_exp(file_array, count, prefix, suffix)
char	*file_array[] ;
int	count ;
char	*prefix, *suffix ;
{
	char	*new_file ;
	int	max_len, pad, length, rc ;

	max_len = MAX_LEN ;
	new_file = (char *) malloc((unsigned int) max_len) ;
	pad = strlen(prefix) + strlen(suffix) + 1 ;

	while (count-- > 0) {
	    length = strlen(file_array[count]) + pad ;
	    if (length > max_len) {
		max_len = 2 * length ;
		free(new_file) ;
		new_file = (char *) malloc((unsigned int) max_len) ;
	    }
	    strcpy(new_file, prefix) ;
	    strcat(new_file, file_array[count]) ;
	    strcat(new_file, suffix) ;

	    my_rename(file_array[count], new_file) ;
	}
	return ;
} /* multi_exp */

/*
 Procedure: multi_rep(file_array, count, old, new)
 Parameters:
	file_array : array of files to be moved.
	count : number of files in above array.
	old : subtring to be replaced.
	new : string to replace substring.
 Description:
	call move for each of the given files.
*/
static void
multi_rep(file_array, count, old, new)
char	*file_array[] ;
int	count ;
char	*old, *new ;
{
	char	*new_file, *substr ;
	int	max_len, pad, rc ;
	int	length, offset ;

	max_len = MAX_LEN ;
	new_file = (char *) malloc((unsigned int) max_len) ;
	pad = strlen(new) - strlen(old) + 1 ;

	if (strlen(old) == 0) {
	    ERROR("rename: no substring given") ;
	    exit(1) ;
	}

	while (count-- > 0) {
	    length = strlen(file_array[count]) + pad ;
	    if (length > max_len) {
		max_len = 2 * length ;
		free(new_file) ;
		new_file = (char *) malloc((unsigned int) max_len) ;
	    }
	    substr = sindex(file_array[count], old) ;
	    if (substr == NULL) {
		fprintf(stderr, "rename: substring not found in %s\n",
			file_array[count]) ;
		continue ;
	    }
	    offset = substr - file_array[count] ;
	    strncpy(new_file, file_array[count], offset) ;
	    new_file[offset] = '\0' ;
	    strcat(new_file, new) ;
	    strcat(new_file, file_array[count] + offset + strlen(old)) ;

	    my_rename(file_array[count], new_file) ;
	}
	return ;
} /* multi_rep */

/*
 Procedure:	my_rename(old, new) ;
 Parameters:
	old = old file name
	new = new file name
 Description:
	call rename and give appropriate error messages.
	if the -i option was given then make sure new doesn't exist.
 Method:
	rename(2), perror(3), and access(2)
*/
static void
my_rename(old, new)
char	*old, *new ;
{
	char	reply[80] ;
	int	rc ;

	if ((i_flag) && (access(new, F_OK) == 0)) {
	    fprintf(stderr, "Ok to replace %s?", new) ;
	    scanf("%s", reply) ;
	    if (reply[0] != 'y') return ;
	}
	rc = rename(old, new) ;
	if (rc != 0) perror(old) ;

	return ;
}

/*
 Function:	sindex(master, sub)
 Parameters:
	master - string in which sub is to be found
	sub - string to look for in master
 Description:
	return a substring pointer to master or NULL if the substring is
	not contained.
*/
static char *
sindex(master, sub)
char *master, *sub ;
{
	char	*mptr, *sptr, *ptr ;
	int	mlen, slen ;

	mlen = strlen(master) ;
	slen = strlen(sub) ;
	if (mlen < slen) return (NULL) ;
	if (slen == 0) return(NULL) ;

	mptr = master ;
	while (strlen(mptr) >= slen) {
	    while (*mptr != sub[0]) {
		if (*mptr == '\0') return (NULL) ;
		mptr ++ ;
	    }
	    sptr = sub ;
	    ptr = mptr ;
	    while (*ptr++ == *sptr++) {
		if (*sptr == '\0') return (mptr) ;
	    }
	    mptr++ ;
	}
	return (NULL) ;
} /* sindex */
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(868 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
BINDEST	      = /usr/local/bin
DOCDEST	      = /usr/man/manl

CC	      = cc
CFLAGS	      = -c -O

LD	      = cc
LDFLAGS	      =
LIBS	      =

OBJS	      = rename.o
SRCS	      = rename.c
HDRS	      =

MAKEFILE      = Makefile
DOC	      = rename.l
PROGRAM	      = rename

SHAR	      = shar
SHARFLAGS     = -v
SHARFILES     = $(SRCS) $(HDRS) $(MAKEFILE) $(DOC) README
SHARFILE      = rename.shar

build:		$(PROGRAM)

$(PROGRAM):     $(OBJS)
		$(LD) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)

install:	$(PROGRAM)
		rm -f $(BINDEST)/$(PROGRAM)
		cp $(PROGRAM) $(BINDEST)
		chmod 755 $(BINDEST)/$(PROGRAM)
		rm -f $(DOCDEST)/$(DOC)
		cp $(DOC) $(DOCDEST)
		chmod 644 $(DOCDEST)/$(DOC)

clean:;		rm -f $(OBJS) $(SHARFILE)

clobber: clean
		rm -f $(PROGRAM)

shar:;		$(SHAR) $(SHARFLAGS) $(SHARFILES) > $(SHARFILE)

.c.o:; $(CC) ${CFLAGS} $<
###
rename.o: /usr/include/stdio.h
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'rename.l'" '(901 characters)'
if test -f 'rename.l'
then
	echo shar: will not over-write existing file "'rename.l'"
else
cat << \SHAR_EOF > 'rename.l'
.TH RENAME
.SH NAME
rename - change the names of a set of files.
.SH SYNOPSIS
\fBrename [-i] file [...] <str1>^|=<str2>\fR
.SH DESCRIPTION
.PP
Rename will change the names of all the given files according to the
command specified as the last argument.  The -i (interactive) option
will prompt the user if the resulting file already exists.

.PP
Here are the valid commands to given in the last argument and what they
stand for:
.br
.in +6c
.ti -5c
<str1>=<str2>	: The string str1 is looked for in each file name and is
replaced with str2.
.ti -5c
<str>=		: The string str is deleted from each file name.
.ti -5c
<str>^		: The string str is added as a prefix to each file name.
.ti -5c
^<str>		: The string str is added as a suffix to each file name.
.ti -5c
<str1>^<str2>	: Combines last two operations.

.PP
The last argument must contain either a `=' or a `^'.

.SH AUTHOR
Gilles Chartrand
.SH BUGS
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'README'" '(79 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
Set up the BINDEST and DOCDEST macros in the makefile and type
	"make install"
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0

ken@rochester.UUCP (03/01/87)

I thought I would share my often used one-liner to change (for example)
.pas suffixes to .p:

ls *.pas | sed 's/\(.*\)\.pas$/mv & \1.p/' | sh

Adding and deleting portions is left as an exercise for the reader.

	Ken

mdoerr@uklirb.UUCP (03/09/87)

I happen to use the following shell script for the same purpose:

---------- Cut here ! -----------
#!/bin/csh
#
# rename:	Globally rename a set of files with a common substring
#		into a set of files with another common substring
#
# example:	Suppose you have the files
#		info-atari16.digest.01 ... info-atari16.digest.30
#		and want to rename these files to
#		dgstia16.001 ... dgstia16.030.
#		Then issue the command
#		rename '*digest*' 'info-atari16\.digest\.' 'dgstia16\.0'
#		and your job is done.
#

foreach index ( $1 )
mv $index `ls $index | sed s/$2/$3/`
end
--------- Cut again ! ----------

	Michael Doerr, Uni. of Kaiserlautern
	...!seismo!unido!uklirb!mdoerr