Skip to content

Commit

Permalink
1.1 (20060124)
Browse files Browse the repository at this point in the history
    - Added one-line program description to -h output
    - Improved cleanup after pod2html
    - Minor reformatting
  • Loading branch information
raforg committed Jan 24, 2006
1 parent 1c579cd commit ac0b602
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 96 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ bindir := $(prefix)/bin
mandir := $(shell [ -d $(prefix)/share/man ] && echo $(prefix)/share/man || echo $(prefix)/man)

name := mved
version := 1.0
date := 20030901
version := 1.1
date := 20060124

install:
@set -e; \
Expand Down
184 changes: 90 additions & 94 deletions mved
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/env perl
$^W = 1;
use warnings;
use strict;

# mved - carefully rename multiple files
#
# Copyright (C) 1997-2003 raf <[email protected]>
# Copyright (C) 1997-2006 raf <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -21,7 +21,7 @@ use strict;
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# or visit http://www.gnu.org/copyleft/gpl.html
#
# 20030901 raf <[email protected]>
# 20060124 raf <[email protected]>

=head1 NAME

Expand All @@ -45,36 +45,35 @@ I<mved> - carefully rename multiple files

=head1 DESCRIPTION

I<mved> renames multiple files. The C<source> argument is a filename
glob specifying the set of files to rename. The C<target> argument is a
pattern specifying the new names for the set of files. The C<source>
argument can contain all of the normal shell globbing constructs (C<?>,
C<*> and C<[...]>) as well as C<=> which is a synonym for C<*>. If any
normal shell globbing constructs are used, they must be quoted to
prevent the shell from performing filename expansion. This is not
necessary when the only construct used is C<=>. There are two styles of
C<target> argument. One allows C<=> to represent the text matching the
(positionally) corresponding glob construct in the C<source> argument.
The other allows C<=#=> (where C<#> is an integer) to represent the text
matching the C<#-th> glob construct in the C<source> argument. The two
styles cannot be mixed.

I<mved> creates new links to the existing files. If the C<-v> verbose
option is supplied, the corresponding I<mv> commands are printed. If any
of them fail, they are all unlinked and the operation is aborted. If all
were successful, the original files are unlinked.

Before renaming any files, I<mved> checks for any dubious consequences.
If a source filename is equal to its corresponding target filename, that
(redundant) renaming operation is skipped. The user is informed unless
the C<-q> quiet option is supplied. If a source filename is equal to
some other target filename, I<mved> gets nervous and exits unless the
C<-f> force option is supplied. If the same filename is a target for
multiple source filenames, I<mved> exits unless the C<-f> force option
is supplied. If any file to be created already exists, I<mved> exits
unless the C<-f> force option is supplied. B<When forced, mved will
unlink any existing target files>. The user will be informed unless the
C<-q> quiet option is supplied.
I<mved> renames multiple files. The C<src> argument is a filename glob
specifying the set of files to rename. The C<dst> argument is a pattern
specifying the new names for the set of files. The C<src> argument can
contain all of the normal shell globbing constructs (C<?>, C<*> and
C<[...]>) as well as C<=> which is a synonym for C<*>. If any normal shell
globbing constructs are used, they must be quoted to prevent the shell from
performing filename expansion. This is not necessary when the only construct
used is C<=>. There are two styles of C<dst> argument. One allows C<=> to
represent the text matching the (positionally) corresponding glob construct
in the C<src> argument. The other allows C<=#=> (where C<#> is an integer)
to represent the text matching the C<#-th> glob construct in the C<src>
argument. The two styles cannot be mixed.

I<mved> creates new links to the existing files. If the C<-v> verbose option
is supplied, the corresponding I<mv> commands are printed. If any of them
fail, they are all unlinked and the operation is aborted. If all were
successful, the original files are unlinked.

Before renaming any files, I<mved> checks for any dubious consequences. If a
source filename is equal to its corresponding destination filename, that
(redundant) renaming operation is skipped. The user is informed unless the
C<-q> quiet option is supplied. If a source filename is equal to some other
destination filename, I<mved> gets nervous and exits unless the C<-f> force
option is supplied. If the same filename is a destination for multiple
source filenames, I<mved> exits unless the C<-f> force option is supplied.
If any file to be created already exists, I<mved> exits unless the C<-f>
force option is supplied. B<When forced, mved will unlink any existing
destination files>. The user will be informed unless the C<-q> quiet option
is supplied.

=head1 OPTIONS

Expand Down Expand Up @@ -106,41 +105,40 @@ manpage properly with a command like:

=item C<-n>

Don't rename anything. Just print the corresponding I<mv> commands and
(and possibly I<rm> commands) then exit.
Don't rename anything. Just print the corresponding I<mv> commands and (and
possibly I<rm> commands) then exit.

=item C<-f>

Force I<mved> to obey even when it doesn't like what you are doing. B<If
you force mved to rename a file to an existing file, the existing file
will be unlinked first>. Never use this without using C<-n> first to see
what you are telling I<mved> to do and verifying that it is what you
really, really want to do.
Force I<mved> to obey even when it doesn't like what you are doing. B<If you
force mved to rename a file to an existing file, the existing file will be
unlinked first>. Never use this without using C<-n> first to see what you
are telling I<mved> to do and verifying that it is what you really, really
want to do.

=item C<-q>

Don't print "Skipping filename" messages when a source filename matches
it's corresponding target filename. Don't print "Unlinking filename"
Don't print "Skipping filename" messages when a source filename matches it's
corresponding destination filename. Don't print "Unlinking filename"
messages when forced to unlink existing files.

=item C<-v>

Print corresponding I<mv> commands when renaming each file. Implied by
the C<-d> option.
Print corresponding I<mv> commands when renaming each file. Implied by the
C<-d> option.

=item C<-d>

Print debugging messages that show the C<source> and C<target> arguments
before and after translation from filename globs into regular
expressions. Also print corresponding I<mv> commands when renaming each
file.
Print debugging messages that show the C<src> and C<dst> arguments before
and after translation from filename globs into regular expressions. Also
print corresponding I<mv> commands when renaming each file.

=item C<-b #>

Specify how many backslashes to count backwards when determining whether
or not special characters are quoted. The default is 4 which should be
more than you'll ever need (unless you have files with consecutive
backslashes in their names - shudder).
Specify how many backslashes to count backwards when determining whether or
not special characters are quoted. The default is 4 which should be more
than you'll ever need (unless you have files with consecutive backslashes in
their names - shudder).

=back

Expand Down Expand Up @@ -185,13 +183,14 @@ backslashes in their names - shudder).

=head1 RETURNS

I<mved> returns 0 (zero) upon success, 1 (one) upon failure. Upon
failure, no files will have been renamed.
I<mved> returns 0 (zero) upon success, 1 (one) upon failure. Upon failure,
no files will have been renamed.

=head1 BUGS

Hard links are used so it is impossible to I<mved> files from one file
system to another. Use I<mv> for this. Then rename with I<mved>.
system to another. Use I<mv> for this. Then rename with I<mved>. This is not
really a bug. It is a safety feature.

Doesn't handle patterns containing pipe C<'|'> characters because this
character is used as the regular expression separator.
Expand All @@ -206,17 +205,17 @@ Released under the terms of the GPL (http://www.gnu.org/copyleft/gpl.html)

=head1 HISTORY

Many years ago on a MIPS far away, there was a program called I<mved>
that renamed multiple files using C<=>. It was very useful but I haven't
seen it since.
Many years ago on a MIPS far away, there was a program called I<mved> that
renamed multiple files using C<=>. It was very useful but I haven't seen it
since.

=head1 SEE ALSO

I<link(2)>, I<unlink(2)>, I<mv(1)>, I<rm(1)>

=head1 AUTHOR

20030901 raf <[email protected]>
20060124 raf <[email protected]>

=head1 URL

Expand All @@ -241,7 +240,8 @@ sub help
" -v - Print equivalent mv commands (implied by -d)\n",
" -d - Print debugging messages\n",
" -b # - Set depth of quote characters to check (default 4)\n",
"\n";
"\n",
"Mved carefully renames multiple files.\n";
exit;
}

Expand All @@ -262,21 +262,19 @@ sub nroff
sub html
{
system "pod2html --noindex $0";
unlink 'pod2html-dircache', 'pod2html-itemcache';
unlink glob 'pod2htm*';
exit;
}

my %opt;
use Getopt::Std;
help() unless getopts('hmwrnfqvdb:', \%opt);
help() if exists $opt{h};
man() if exists $opt{m};
nroff() if exists $opt{r};
html() if exists $opt{w};
help() unless $#ARGV == 1;

my $src_glob = $ARGV[0];
my $dst_glob = $ARGV[1];
help if !getopts('hmwrnfqvdb:', \%opt) || exists $opt{h};
man if exists $opt{m};
nroff if exists $opt{r};
html if exists $opt{w};
help unless @ARGV == 2;
my $src_glob = shift;
my $dst_glob = shift;
my $testing = exists $opt{n};
my $force = exists $opt{f};
my $quiet = exists $opt{q};
Expand All @@ -286,17 +284,17 @@ my $backwards = exists $opt{b} ? $opt{b} : 4;

print "$name: glob $src_glob $dst_glob\n" if $debug;

# construct a glob and get the list of matching files
# Construct a glob and get the list of matching files

$src_glob =~ s/=/*/g;
my @src = glob($src_glob);
die "$name: No such file: $src_glob\n" if $#src == -1;
my @src = glob $src_glob ;
die "$name: No such file: $src_glob\n" unless @src;

# translate src into a regular expression search
# Translate src into a regular expression search

my $src_re = $src_glob;
my $unsloshed = '';
$unsloshed = "(?<!" . $unsloshed . "\\\\)" for 1 .. $backwards;
$unsloshed = "(?<!" . $unsloshed . "\\\\)" for 1..$backwards;
my $head = qr/(?:\^|!)/;
my $char = qr/(?:[^\]]|\\.)/;
my $body_part = qr/(?::\w+:|$char-$char|$char)/;
Expand All @@ -320,7 +318,7 @@ for my $rep (@rep)
$src_re =~ s/^/^/;
$src_re =~ s/$/\$/;

# translate dst into a regular expression replacement
# Translate dst into a regular expression replacement

my $dst_re = $dst_glob;
my $explicit_target = qr/$unsloshed=(\d+)=/;
Expand All @@ -342,7 +340,7 @@ else
print "$name: re s|$src_re|$dst_re|\n" if $debug;
die "pattern contains '|'\n" if $src_re =~ /\|/ || $dst_re =~ /\|/;

# construct the list of dst file names
# Construct the list of dst file names

my @dst;
my $old;
Expand All @@ -355,18 +353,18 @@ for $old (@src)
push @dst, $new;
}

# must be ultra paranoid but helpful
# Must be ultra paranoid but helpful

my $help = "Use -n to check and then -f to force it iff you are certain";

my %dst_chk;
for (my $i = 0; $i <= $#dst; ++$i)
for (my $i = 0; $i < @dst; ++$i)
{
die "$name: Aborting: target $dst[$i] appears multiple times\n" if !$testing && !$force && exists $dst_chk{$dst[$i]};
$dst_chk{$dst[$i]} = $i;
}

for (my $i = 0; $i <= $#src; ++$i)
for (my $i = 0; $i < @src; ++$i)
{
if (exists $dst_chk{$src[$i]})
{
Expand All @@ -385,31 +383,31 @@ for (my $i = 0; $i <= $#src; ++$i)
}
}

for (my $i = 0; $i <= $#dst; ++$i)
for (my $i = 0; $i < @dst; ++$i)
{
die "$name: Aborting: $dst[$i] already exists\n$help\n"
if -e $dst[$i] && !$testing && !$force;
}

# if testing, print out corresponding mv commands then exit
# If testing, print out corresponding mv commands then exit

if ($testing)
{
for (my $i = 0; $i <= $#src; ++$i)
for (my $i = 0; $i < @src; ++$i)
{
my $r = (-d $dst[$i]) ? 'r' : '';
print "rm -${r}f ", $dst[$i], ' (if forced)', "\n" if -e $dst[$i];
print 'mv ', $src[$i], ' ', $dst[$i], "\n";
}

exit(0);
exit;
}

# if forced, first unlink any existing destination files :[
# If forced, first unlink any existing destination files :[

if ($force)
{
for (my $i = 0; $i <= $#src; ++$i)
for (my $i = 0; $i < @src; ++$i)
{
if (-d $dst[$i])
{
Expand All @@ -424,10 +422,10 @@ if ($force)
}
}

# try to move all of the files
# Try to move all of the files

my $i;
for ($i = 0; $i <= $#src; ++$i)
for ($i = 0; $i < @src; ++$i)
{
print "mv $src[$i] $dst[$i]\n" if $verbose;

Expand All @@ -441,11 +439,11 @@ for ($i = 0; $i <= $#src; ++$i)
}
}

# if any failed, abandon and remove all destination files
# If any failed, abandon and remove all destination files

if ($i != $#src + 1)
if ($i != @src)
{
for ($i = 0; $i <= $#src; ++$i)
for ($i = 0; $i < @src; ++$i)
{
if (-d $dst[$i])
{
Expand All @@ -460,10 +458,8 @@ if ($i != $#src + 1)
die "$name: Aborting: Failed to mv $src[$i] $dst[$i] ($!)\n";
}

# otherwise, remove the originals
# Otherwise, remove the originals

unlink @src;

exit;

# vi:set ts=4 sw=4:

0 comments on commit ac0b602

Please sign in to comment.