Donghoon Park
Donghoon Park

Reputation: 25

Increase file name number by shell or linux command

I have files, for example

- public_00000.jpg
- public_00001.jpg
- ...
- public_00535.jpg

But I want to make these files as

- public_05674.jpg
- public_05675.jpg
- ...
- public_06209.jpg

I mean, I want to increase the number in the filename by +5674 on the whole.

How can I do this by Shell or Command??

Thanks ahead:)

Upvotes: 2

Views: 971

Answers (2)

RavinderSingh13
RavinderSingh13

Reputation: 133710

Could you please try following.

for file in *.jpg
do
   first_filename_part="${file%_*}"
   last_filename_part="${file#*.}"
   var="${file#*_}"
   count="${var%.*}"
   ((count = count + 5674))
   printf "%s %s %s_%05d.%s\n" "mv"  $file $first_filename_part $count $last_filename_part
done

Above will only print the commands on screen like:

mv public_00000.jpg public_05674.jpg


Try running only 1 command First from above printed output on your terminal, once you are Happy with results try following then, since this will rename all the files.

for file in *.jpg
do
   first_filename_part="${file%_*}"
   last_filename_part="${file#*.}"
   var="${file#*_}"
   count="${var%.*}"
   ((count = count + 5674))
   printf "%s %s %s_%05d.%s\n" "mv"  $file $first_filename_part $count $last_filename_part | bash
done


From man page: I have used parameter expansion mechanism.

${parameter#word}

${parameter##word} Remove matching prefix pattern. The word is expanded to produce a pattern just as in pathname expansion. If the pattern matches the beginning of the value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the #'' case) or the longest matching pattern (the##'' case) deleted. If parameter is @ or *, the pattern removal operation is applied to each positional parame- ter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.

${parameter%word}

${parameter%%word} Remove matching suffix pattern. The word is expanded to produce a pattern just as in pathname expansion. If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the %'' case) or the longest matching pattern (the%%'' case) deleted. If parameter is @ or *, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.

Upvotes: 4

Mark Setchell
Mark Setchell

Reputation: 207778

You can use Perl rename like this to do an "evaluated substitution" - that's the e right at the end:

rename --dry-run 's|(\d+)|sprintf("%05d",$1+5674)|e' pub*jpg

Sample Output

'public_00000.jpg' would be renamed to 'public_05674.jpg'
'public_00001.jpg' would be renamed to 'public_05675.jpg'

In case you are unfamiliar with Perl, the command basically says:

rename "substitute|THIS|with THAT|" IN_THESE_FILENAMES

In your case, THIS is \d+ which means "one or more digits" and that is enclosed within parentheses to make a "capture group". That group can then be referred to in the substitution on the right side by $1 since it is the first capture group.

The THAT in your case is simply a print statement that prints the first capture group $1 incremented by 5674 in a field that is zero-padded to be 5 digits wide using %05d.


Using Perl rename has the benefits that:

  • you can do a "dry run" to see what it would do without actually doing anything
  • it will not clobber (overwrite) files without warning
  • it is fast - it doesn't create a process for sed and another for mv for every single file, it just starts a single Perl interpreter and makes a library call to rename each file
  • it will automagically create any intermediate directories needed, if you wish
  • you can use the full power of Perl to do as much substitution or calculation as you wish

Note for macOS users... Perl is installed on macOS by default, so if you use homebrew to install your packages, you just need:

brew install rename

Note for Linux users... there are several rename packages, the one I am referring to is sometimes called prename, or "Perl rename". That means, if you run file on the rename command, it should say it's a Perl script like this:

file $(which rename)
/usr/local/bin/rename: Perl script text executable

Upvotes: 3

Related Questions