Get the Perl Rename Utility Instead of the Built-In Rename

Get the Perl rename utility instead of the built-in rename

I can only speak for Debian. The two programs are called

  • /usr/bin/rename.ul from the util-linux package (hence the .ul suffix)
  • /usr/bin/prename from the perl package

The actual rename command works via the /etc/alternatives mechanism, whereby

  • /usr/bin/rename is a symlink to /etc/alternatives/rename
  • /etc/alternatives/rename is a symlink to /usr/bin/prename

The same problem has been bugging me on Cygwin, which is a Red Hat product, so should be more similar to Fedora. I'll have a look on my company laptop on Monday. And I remember the Perl-rename having worked there sometimes. Probably before I installed util-linux.

If you install the Perl-rename to /usr/local/bin it will have precedence over rename from util-linux. Same goes for the manpage when installed to /usr/local/share/man/man1/.

I've just created a separate Perl-rename package on Github: https://github.com/subogero/rename

Using the perl-based rename command to change filenames commencing with dashes

Many commands, including Perl's rename script, support a double-dash to denote the end of a command's options. Hence, to rename --the-file-name to the-file-name:

rename 's/-//g' -- --the-file-name

Perl's Getopt::Long module supports this and is used by rename.

In general, see also: https://unix.stackexchange.com/questions/11376/what-does-double-dash-mean-also-known-as-bare-double-dash

How can i find and rename multiple files

Possible solution with Perl rename:

find /mydir -depth -type f -exec rename -v 's/(.*\/)?([^.]*)/$1\U$2/' {} +

The commands in the question have several problems.

You seem to confuse the syntax of find's -exec action and xargs.

find /mydir -depth -type f -exec rename -v 'substitution_command' {} \;
find /mydir -depth -type f| xargs -n 1 rename -v 'substitution_command'

The xargs version has problems in case a file name contains a space.

If you replace \; with +, multiple file names are passed to one invocation of rename.


The substitution command is only supported by the Perl version of the rename command. You might have to install this version. See Get the Perl rename utility instead of the built-in rename


The substitution did not work in my test. I successfully used

rename -v 's/(.*\/)?([^.]*)/$1\U$2/' file ...

The first group (.*\/)? optionally matches a sequence of characters with a trailing /. This is used to copy the directory unchanged.

The second group ([^.]*) matches a sequence of characters except ..

This is the file name part before the first dot (if any) which will be converted to uppercase. In case the file name has more than one extension, all will remain unchanged, e.g.

Path/To/Foo.Bar.Baz -> Path/To/FOO.Bar.Baz

rename -n option seems not available under cygwin

On Cygwin rename program comes from util-linux, see the bottom of man rename:

The rename command is part of the util-linux package and is available
from ftp://ftp.kernel.org/pub/linux/utils/util-linux/.

On some (most?) Linux distributions rename is a short Perl script. If you have Perl installed on your Cygwin installation just copy rename script and run it.

Bulk renaming files with bash and Perl based on file name

In bash, you could write something like:

for file in *-\(ab-[0-9]*\)*; do
newfile="${file/-(ab-[0-9]*)/}"
mv "$file" "$newfile"
done

user perl's rename in Windows cmd.exe, like in linux/bash?

If calling a perl script for your renaming needs is good enough for you on Linux, they why not do it on Windows too? Both ActiveState & Strawberry will modify your registry to associate .pl files with their implementation of perl.

Copy the script to Windows, add a .pl extension & make sure it's in your PATH.

If you'd like to call it without typing in the '.pl' then you can even tell windows that .pl is an 'executable extension' with the PATHEXT environment variable. Of course if you do this then you should heed the warning below & use a name that doesn't conflict with the OS built-ins. (Good catch, Ikegami)

Renaming and Moving Files in Bash or Perl

As per OP, this can be Perl, not just bash. Here we go

NEW SOLUTION: (paying attention to extension)

~/junk/a1$ ls
f1.txt f2.txt f3.txt z1 z2


~/junk/a1$ ls ../a2
f1.txt f2.1.txt f2.2.txt f2.3.txt f2.txt z1

# I split the one-liner into multiple lines for readability
$ perl5.8 -e
'{use strict; use warnings; use File::Copy; use File::Basename;
my @files = glob("*"); # assume current directory
foreach my $file (@files) {
my $file_base2 = basename($file);
my ($file_base, $ext) = ($file_base2 =~ /(.+?)([.][^.]+$)?$/);
my $new_file_base = "../a2/$file_base";
my $new_file = $new_file_base . $ext;
my $counter = 1;
while (-e $new_file) {
$new_file = "$new_file_base." . $counter++ . $ext;
}
copy($file, $new_file)
|| die "could not copy $file to $new_file: $!\n";
} }'

~/junk/a1> ls ../a2
f1.1.txt f1.txt f2.1.txt f2.2.txt f2.3.txt f2.4.txt f2.txt f3.txt
z1 z1.1 z2

OLD SOLUTION: (not paying attention to extension)

~/junk/a1$ ls
f1 f2 f3

~/junk/a1$ ls ../a2
f1 f2 f2.1 f2.2 f2.3

# I split the one-liner into multiple lines for readability
$ perl5.8 -e
'{use strict; use warnings; use File::Copy; use File::Basename;
my @files = glob("*"); # assume current directory
foreach my $file (@files) {
my $file_base = basename($file);
my $new_file_base = "../a2/$file_base";
my $new_file = $new_file_base;
my $counter = 1;
while (-e $new_file) { $new_file = "$new_file_base." . $counter++; }
copy($file,$new_file)
|| die "could not copy $file to $new_file: $!\n";
} }'

~/junk/a1> ls ../a2
f1 f1.1 f2 f2.1 f2.2 f2.3 f2.4 f3


Related Topics



Leave a reply



Submit