Reputation: 23
I have extracted clips from a video with ffmpeg, following this pattern 'clip-%4d.png'.
This has yielded files like: clip-0001.png
, clip-0002.png
and so on.
I have then applied many filters with imagemagick "convert" to those pictures, and it ran for a couple hours.
I realised my list order is broken after clip-9999.png
, it becomes clip-10000.png
and up to clip-40000.png
, successfully ruining my sequence of clips.
I would like to convert all my clips to follow the sequence clip-00000.png
, clip-00001.png
up to clip-40000.png
.
I could restart the whole process using pattern 'clip-%5d', but I am told rename
utility might solve my problem; however I am myself quite unfamiliar with regular expressions.
Upvotes: 2
Views: 391
Reputation: 753525
rename
commandIf you've got a Perl-based rename
command, that's pretty easy:
rename 's/(\d{4})/0$1/' *-????.png
I note in passing that if you've really got about 10,000 clips to rename, you may need to work with xargs
or find
to avoid problems with 'argument list too long'.
find . -name 'clip-????.png' -exec rename 's/(\{4})/0$1/' {} +
or:
find . -name 'clip-????.png' -print | xargs rename 's/(\d{4})/0$1/'
Since your names don't contain spaces, either will work. If there are spaces to worry about, use the find
-only variant, assuming your find
supports the POSIX 2008 +
notation to find
. This can be applied to any of the other answers with a little care.
I note that this Perl script avoids having to execute mv
10,000 times, so it is likely to outpace any of the shell scripts that executes mv
for each file rename. For a one-off exercise, this may not matter, but it will become more of an issue when you get to more than 100,000 clips.
Also, the script below has the option to read the file names, one per line, but it slurps the whole lot into memory, which isn't dreadfully efficient (but was present in the original version of the script and has been kept, even though I've hardly ever used the option). Assuming a sane modern machine (say 1 GiB of memory, but less would be sufficient), that is not going to be a problem with just 10,000 names of length 12 characters each. So you could also use:
find . -name 'clip-????.png' -print | rename 's/(\d{4})/0$1/'
rename
scriptIf you've not got a Perl-based rename
command, this is the one I use. It was originally from the 1st Edition of the Camel Book, but has been modified a little over the years:
#!/usr/bin/env perl
#
# @(#)$Id: rename.pl,v 1.8 2011/06/03 22:30:22 jleffler Exp $
#
# Rename files using a Perl substitute or transliterate command
use strict;
use warnings;
use Getopt::Std;
my(%opts);
my($usage) = "Usage: $0 [-fnxV] perlexpr [filenames]\n";
my($force) = 0;
my($noexc) = 0;
my($trace) = 0;
die $usage unless getopts('fnxV', \%opts);
if ($opts{V})
{
printf "%s\n", q'RENAME Version $Revision: 1.8 $ ($Date: 2011/06/03 22:30:22 $)';
exit 0;
}
$force = 1 if ($opts{f});
$noexc = 1 if ($opts{n});
$trace = 1 if ($opts{x});
my($op) = shift;
die $usage unless defined $op;
if (!@ARGV) {
@ARGV = <STDIN>;
chop(@ARGV);
}
for (@ARGV)
{
if (-e $_ || -l $_)
{
my($was) = $_;
eval $op;
die $@ if $@;
next if ($was eq $_);
if ($force == 0 && -f $_)
{
print STDERR "rename failed: $was - $_ exists\n";
}
else
{
print "+ $was --> $_\n" if $trace;
print STDERR "rename failed: $was - $!\n"
unless ($noexc || rename($was, $_));
}
}
else
{
print STDERR "$_ - $!\n";
}
}
Upvotes: 2
Reputation: 67211
you can check here:
you can replace the command gsub(/-\(.*\)/,"",$0);
in the link with
gsub(/-/,"-0",$0);
and the ls -1
part will be replaced with ls -1 clip-????.png
also you need to remove the search part in the awk command.
I tested below with a sample file.
@jonathan,I did not really understand what you said.But below is test i made:
> ls -1 clip-????.png
clip-0003.png
clip-1111.png
> ls -1 clip-????.png | nawk '{old=$0;gsub(/-/,"-0",$0);system("mv \""old"\" "$0)}'
phoenix.332> ls -1 clip-?????.png
clip-00003.png
clip-01111.png
> ls -1 clip-????.png
ls: No match.
nawk is on solaris . you can use awk for other flavours of unix.
Upvotes: 0
Reputation: 10162
Use this command in bash:
for file in clip-????.png ; do
mv ${file} clip-0${file#clip-}
done
to check that the command will do the right thing, replace "mv" with "echo mv" to see the list of renamings that will be done.
Upvotes: 5
Reputation: 409146
You could do something like this:
for f in clip-[0-9][0-9][0-9][0-9].png; do mv $f `echo $f | sed 's/clip-/clip-0/'`; done
Note: To test without actually doing anything, replace mv
with echo mv
.
Upvotes: 2