Add prename recipe
This commit is contained in:
parent
005f2f8c00
commit
cf0c5ad30a
17
recipes/prename/Makefile
Normal file
17
recipes/prename/Makefile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
name = prename
|
||||||
|
version = 1.0
|
||||||
|
release = 0
|
||||||
|
|
||||||
|
dependencies = perl
|
||||||
|
|
||||||
|
# skip download, configuration, build, install
|
||||||
|
create_steps = create_fake_root_dir fake_root_install_custom package_base clean_working_dir
|
||||||
|
|
||||||
|
fake_root_install_custom:
|
||||||
|
#$(Q)install -d -m0555 "$(pkg_fake_root_dir)/$(BINDIR)/"
|
||||||
|
$(Q)mkdir -p "$(pkg_fake_root_dir)/$(BINDIR)/"
|
||||||
|
$(Q)cp prename "$(pkg_fake_root_dir)/$(BINDIR)/"
|
||||||
|
|
||||||
|
|
||||||
|
SYSCONF ?= ../../
|
||||||
|
include $(SYSCONF)/package.mk
|
278
recipes/prename/prename
Executable file
278
recipes/prename/prename
Executable file
@ -0,0 +1,278 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
rename - renames multiple files
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
F<rename>
|
||||||
|
B<-h>
|
||||||
|
|
||||||
|
F<rename>
|
||||||
|
S<B<[ -0 ]>>
|
||||||
|
S<B<[ -c | -C ]>>
|
||||||
|
S<B<[ -e code ]>>
|
||||||
|
S<B<[ -f ]>>
|
||||||
|
S<B<[ -i ]>>
|
||||||
|
S<B<[ -l | -L ]>>
|
||||||
|
S<B<[ -n ]>>
|
||||||
|
S<B<[ -s from to ]>>
|
||||||
|
S<B<[ -v ]>>
|
||||||
|
S<B<[ files ]>>
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
C<rename> renames the filenames supplied according to the rules specif
|
||||||
|
+ied. If a given filename is not modified, it will not be renamed. If
|
||||||
|
+no filenames are given on the command line, filenames will be read vi
|
||||||
|
+a standard input.
|
||||||
|
|
||||||
|
For example, to rename all files matching C<*.bak> to strip the extens
|
||||||
|
+ion, you might say
|
||||||
|
|
||||||
|
rename 's/\.bak$//' *.bak
|
||||||
|
|
||||||
|
If are confident that none of the filenames has C<.bak> anywhere else
|
||||||
|
+than at the end, you can also use the much easier typed
|
||||||
|
|
||||||
|
rename -s .bak '' *.bak
|
||||||
|
|
||||||
|
You can always do multiple changes in one ago:
|
||||||
|
|
||||||
|
rename -s .tgz .tar.gz -s .tbz2 .tar.bz2 *.tar.*
|
||||||
|
|
||||||
|
Note however that expressive options are order sensitive. The followin
|
||||||
|
+g would probably surprise you:
|
||||||
|
|
||||||
|
rename -s foo bar -s bar baz *
|
||||||
|
|
||||||
|
Because changes are cumulative, this would end up substituting a F<foo
|
||||||
|
+> match in a filename with F<baz>, not F<bar>! To get the intended re
|
||||||
|
+sults in the above example, you could reverse the order of options:
|
||||||
|
|
||||||
|
rename -s bar baz -s foo bar *
|
||||||
|
|
||||||
|
If you placed the C<-c> after the C<-e> in the above example, files wi
|
||||||
|
+th F<.zip> and F<.ZIP> extensions would be (attempted to be) moved to
|
||||||
|
+ different directories.
|
||||||
|
|
||||||
|
To translate uppercase names to lower, you'd use
|
||||||
|
|
||||||
|
rename -c *
|
||||||
|
|
||||||
|
If you have files with control characters and blanks in their names, C
|
||||||
|
+<-z> will clean them up.
|
||||||
|
|
||||||
|
rename -z *
|
||||||
|
|
||||||
|
You can combine all of these to suit your needs. F.ex files from Windo
|
||||||
|
+ws systems often have blanks and (sometimes nothing but) capital lett
|
||||||
|
+ers. Let's say you have a bunch of such files to clean up, and you al
|
||||||
|
+so want to move them to subdirectories based on extension. The follow
|
||||||
|
+ing command should help, provided all directories already exist:
|
||||||
|
|
||||||
|
rename -cz -e '$_ = "$1/$_" if /(\..*)\z/' *
|
||||||
|
|
||||||
|
Again you need to pay attention to order sensitivity for expressive op
|
||||||
|
+tions. If you placed the C<-c> after the C<-e> in the above example,
|
||||||
|
+files with F<.zip> and F<.ZIP> extensions would be (attempted to be)
|
||||||
|
+moved to different directories because the directory name prefix woul
|
||||||
|
+d be added before the filenames were normalized.
|
||||||
|
|
||||||
|
=head1 ARGUMENTS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item B<-h>, B<--help>
|
||||||
|
|
||||||
|
Browse the manpage.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 OPTIONS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item B<-0>, B<--null>
|
||||||
|
|
||||||
|
When reading file names from C<STDIN>, split on null bytes instead of
|
||||||
|
+newlines. This is useful in combination with GNU find's C<-print0> op
|
||||||
|
+tion, GNU grep's C<-Z> option, and GNU sort's C<-z> option, to name j
|
||||||
|
+ust a few. B<Only valid if no filenames have been given on the comman
|
||||||
|
+dline.>
|
||||||
|
|
||||||
|
=item B<-c>, B<--lower-case>
|
||||||
|
|
||||||
|
Converts file names to all lower case.
|
||||||
|
|
||||||
|
=item B<-C>, B<--upper-case>
|
||||||
|
|
||||||
|
Converts file names to all upper case.
|
||||||
|
|
||||||
|
=item B<-e>, B<--expr>
|
||||||
|
|
||||||
|
The C<code> argument to this option should be a Perl expression that a
|
||||||
|
+ssumes the filename in the C<$_> variable and modifies it for the fil
|
||||||
|
+enames to be renamed. When no other C<-c>, C<-C>, C<-e>, C<-s>, or C<
|
||||||
|
+-z> options are given, you can omit the C<-e> from infront of the cod
|
||||||
|
+e.
|
||||||
|
|
||||||
|
=item B<-f>, B<--force>
|
||||||
|
|
||||||
|
Rename even when a file with the destination name already exists.
|
||||||
|
|
||||||
|
=item B<-i>, B<--interactive>
|
||||||
|
|
||||||
|
Ask the user to confirm every action before it is taken.
|
||||||
|
|
||||||
|
=item B<-l>, B<--symlink>
|
||||||
|
|
||||||
|
Create symlinks from the new names to the existing ones, instead of re
|
||||||
|
+naming the files. B<Cannot be used in conjunction with C<-L>.>
|
||||||
|
|
||||||
|
=item B<-L>, B<--hardlink>
|
||||||
|
|
||||||
|
Create hard links from the new names to the existing ones, instead of
|
||||||
|
+renaming the files. B<Cannot be used in conjunction with C<-l>.>
|
||||||
|
|
||||||
|
=item B<-n>, B<--dry-run>, B<--just-print>
|
||||||
|
|
||||||
|
Show how the files would be renamed, but don't actually do anything.
|
||||||
|
|
||||||
|
=item B<-s>, B<--subst>, B<--simple>
|
||||||
|
|
||||||
|
Perform a simple textual substitution of C<from> to C<to>. The C<from>
|
||||||
|
+ and C<to> parameters must immediately follow the argument.
|
||||||
|
|
||||||
|
This is equivalent to supplying a C<perlexpr> of C<s/\Qfrom/to/>.
|
||||||
|
|
||||||
|
=item B<-v>, B<--verbose>
|
||||||
|
|
||||||
|
Print additional information about the operations (not) executed.
|
||||||
|
|
||||||
|
=item B<-z>, B<--sanitize>
|
||||||
|
|
||||||
|
Replaces consecutive blanks, shell meta characters, and control charac
|
||||||
|
+ters in filenames with underscores.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
mv(1), perl(1), find(1), grep(1), sort(1)
|
||||||
|
|
||||||
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
Aristotle Pagaltzis
|
||||||
|
|
||||||
|
Original code from Larry Wall and Robin Barker.
|
||||||
|
|
||||||
|
=head1 BUGS
|
||||||
|
|
||||||
|
None currently known.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
use Pod::Usage;
|
||||||
|
use Getopt::Long;
|
||||||
|
|
||||||
|
sub DEBUG { print "@_\n" if $::LEVEL >= 2 }
|
||||||
|
sub INFO { print "@_\n" if $::LEVEL >= 1 }
|
||||||
|
sub ERROR { print "@_\n" }
|
||||||
|
|
||||||
|
my @perlexpr;
|
||||||
|
|
||||||
|
Getopt::Long::Configure(qw(bundling no_ignore_case));
|
||||||
|
GetOptions(
|
||||||
|
'h|help' => sub { pod2usage( -verbose => 2 ) },
|
||||||
|
'0|null' => \my $opt_null,
|
||||||
|
'c|lower-case' => sub { push @perlexpr, 's/([[:upper:]]+)/\L$1/g' },
|
||||||
|
'C|upper-case' => sub { push @perlexpr, 's/([[:lower:]]+)/\U$1/g' },
|
||||||
|
'e|expr=s' => \@perlexpr,
|
||||||
|
'f|force' => \my $opt_force,
|
||||||
|
'i|interactive' => \my $opt_interactive,
|
||||||
|
'l|symlink' => \my $opt_symlink,
|
||||||
|
'L|hardlink' => \my $opt_hardlink,
|
||||||
|
'n|just-print|dry-run' => \my $opt_dryrun,
|
||||||
|
's|subst|simple' => sub {
|
||||||
|
pod2usage( -verbose => 1 ) if @ARGV < 2;
|
||||||
|
my @param = map(quotemeta, splice @ARGV, 0, 2);
|
||||||
|
# NB: ${\"..."} is necessary because unknown backslash escapes are not
|
||||||
|
# treated the same in pattern- vs doublequote-quoting context, and we need
|
||||||
|
# the latter to do the right thing with user input like 'foo{bar}baz'
|
||||||
|
push @perlexpr, sprintf 's/\Q${\"%s"}\E/%s/', @param;
|
||||||
|
},
|
||||||
|
'v|verbose+' => \my $opt_verbose,
|
||||||
|
'z|sanitize' => sub { push @perlexpr, 's/[!"$&()=?`*\';<>|_[:cntrl:][:blank:]]+/_/g' },
|
||||||
|
) or pod2usage( -verbose => 1 );
|
||||||
|
|
||||||
|
pod2usage( -verbose => 1 ) if $opt_hardlink and $opt_symlink;
|
||||||
|
|
||||||
|
if(not @perlexpr) {
|
||||||
|
if(@ARGV) { push @perlexpr, shift }
|
||||||
|
else { pod2usage( -verbose => 1 ) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pod2usage( -verbose => 1 ) if $opt_null and @ARGV;
|
||||||
|
|
||||||
|
$::LEVEL = ($opt_verbose || 0) + ($opt_dryrun || 0);
|
||||||
|
|
||||||
|
my $code = do {
|
||||||
|
my $cat = "sub { ".join('; ', @perlexpr)." }";
|
||||||
|
DEBUG("Using expression: $cat");
|
||||||
|
my $evaled = eval $cat;
|
||||||
|
die $@ if $@;
|
||||||
|
die "Could not evaluate to code ref\n" unless 'CODE' eq ref $evaled;
|
||||||
|
$evaled;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!@ARGV) {
|
||||||
|
INFO("Reading filenames from STDIN");
|
||||||
|
@ARGV = do {
|
||||||
|
if($opt_null) {
|
||||||
|
INFO("Splitting on null bytes");
|
||||||
|
local $/ = "\0";
|
||||||
|
}
|
||||||
|
<STDIN>;
|
||||||
|
};
|
||||||
|
chomp @ARGV;
|
||||||
|
}
|
||||||
|
|
||||||
|
my ($verb, $verbed, $action) =
|
||||||
|
$opt_hardlink ? ( qw(link linked), sub { link shift, shift } ) :
|
||||||
|
$opt_symlink ? ( qw(symlink symlinked), sub { symlink shift, shift } ) :
|
||||||
|
do { qw(rename renamed), sub { rename shift, shift } };
|
||||||
|
|
||||||
|
for (@ARGV) {
|
||||||
|
my $oldname = $_;
|
||||||
|
|
||||||
|
$code->();
|
||||||
|
|
||||||
|
if($oldname eq $_) {
|
||||||
|
DEBUG("'$oldname' unchanged");
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ERROR("'$oldname' not $verbed: '$_' already exists"), next
|
||||||
|
if not $opt_force and -e;
|
||||||
|
|
||||||
|
if($opt_interactive and not $opt_dryrun) {
|
||||||
|
print "\u$verb '$oldname' to '$_' (y/n)? ";
|
||||||
|
if(<STDIN> !~ /^y/i) {
|
||||||
|
DEBUG("Skipping '$oldname'.");
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($opt_dryrun or $action->($oldname, $_)) {
|
||||||
|
INFO("'$oldname' $verbed to '$_'");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ERROR("Can't $verb '$oldname' to '$_': $!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INFO('Dry run, no changes were made.') if $opt_dryrun;
|
Loading…
Reference in New Issue
Block a user