I have a large number of files with names file00.txt, file01.txt etc in a folder. Is it possible to rename all where the numbers will change to (4000+200*number) in terminal? I want the name of the final files as file4000.txt, file4200.txt etc. Thanks!!
3 Answers
If you have zsh
installed...
autoload zmv
zmv -n '(file)(<->)(.txt)' '$1$((4000+$2*200))$3'
remove the -n
if you're happy with the result.
I would normally use rename
which makes use of perlre
$ rename -v 's/^(file)(\d+)(\.txt)$/$1 . (4000+200*$2) . $3/e' *.txt
file00.txt renamed as file4000.txt
file01.txt renamed as file4200.txt
or as Glenn Jackman suggests in the comments;
$ rename -v 's/(\d+)/4000 + 200*$1/e' file*.txt
Explanation:
This uses the s/foo/bar/
syntax which substitutes foo
with bar
.
foo
is ^(file)(\d+)(.txt)
. So the expression will match any file starting with foo
, containing 1 or more digits, followed by a .txt
extension and nothing else. file
is saved in capture group 1, the digits in capture group 2, and .txt
in capture group 3.
Then we replace bar
with our new filename: $1 . (4200 + $2) . $3
. We are adding 4200 to capture group 2 (the digits) and concatenating that with $1
and $3
.
We need the e
modifier in s/foo/bar/e
to ensure (4000 + 200*$2)
and the concatenation is actually evaluated.
I added -v
so it prints what is changed, but while testing, you'll want to use -n
so it doesn't change anything until you are happy with what it will actually do.
The last argument to the rename
command is *.txt
. This is simply the list of files to evaluate. Since we do a check for the extension in perlre
, we could just use a *
here. Anything that doesn't match (foo
) will not be changed.
This answer uses file-rename
from Debian's package rename which uses update-alternatives
to provide /usr/bin/rename
. If you don't have that package installed, you may have rename.ul
from util-linux. rename.ul
uses different expression system and will not work with what I've described here.
-
1Can be slightly simplified:
rename -v 's/(\d+)/4000 + 200*$1/e' file*.txt
(fixed the formula in passing) Mar 22 at 13:46 -
3Note that this assumes
perl-rename
, while on many systems, therename
command is actually rename from util-linux instead. Oh, and the OP wants4000 + (200 * $2)
, so not adding 4200, but adding 4000 to the result of multiplying the number by 200.– terdon ♦Mar 22 at 13:49
If you don't want to rename all of the files and you just want to rename some of the files within a certain range, then a modified version of the solution from this answer to How to rename files with sequential names to an another sequence using Terminal? may be of some use.
For example, to rename just file05.txt
through to file11.txt
to file5000.txt
to file7200.txt
:
for index in {05..11}; do echo mv file"${index}".txt file"$((4000+index*200))".txt; done
The echo
is there just to test that the command does what you expect it to. Remove the echo
once the output looks correct.
Note for single digits (numbers <10)
For the files in the file01.txt
to file09.txt
range, a 0
must be added to precede the single digit in the range. Therefore, instead of
for index in {5..11};
you would put
for index in {05..11};
For a range of double digits, then the preceding 0
is not required. For example, for 13 to 25:
for index in {13..25};
rename
and if we don't know your OS, we won't know which one you have.