Rename files with zero padded numbers while keeping extension using “rename” command

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












0















I want to rename files with zero padded numbers while keeping extension.

Example

a.abc

b.cde

c.xyz



to be renamed as

001.abc

002.cde

003.xyz



:~/x$ rename -n -v 's/.+/our $i; sprintf("%03d.jpg", 1+$i++)/e' *
#output>
rename(a.abc, 001.jpg)
rename(b.cde, 002.jpg)
rename(c.xyz, 003.jpg)
#then
:~/x$ echo "a.abc"
a.abc
:~/x$ echo $_##*.
#output>
abc
so I tried>
:~/x$ rename -n -v 's/.+/our $i; sprintf("%03d.$_##*.", 1+$i++)/' *
Global symbol "$i" requires explicit package name (did you forget to declare "my $i"?) at (user-supplied code).
Missing right curly or square bracket at (user-supplied code), within string
syntax error at (user-supplied code), at EOF


Any suggestions using "rename" command?










share|improve this question
























  • You're trying to stuff the shell variable expansion $_##.* into perl.

    – glenn jackman
    Mar 5 at 21:08















0















I want to rename files with zero padded numbers while keeping extension.

Example

a.abc

b.cde

c.xyz



to be renamed as

001.abc

002.cde

003.xyz



:~/x$ rename -n -v 's/.+/our $i; sprintf("%03d.jpg", 1+$i++)/e' *
#output>
rename(a.abc, 001.jpg)
rename(b.cde, 002.jpg)
rename(c.xyz, 003.jpg)
#then
:~/x$ echo "a.abc"
a.abc
:~/x$ echo $_##*.
#output>
abc
so I tried>
:~/x$ rename -n -v 's/.+/our $i; sprintf("%03d.$_##*.", 1+$i++)/' *
Global symbol "$i" requires explicit package name (did you forget to declare "my $i"?) at (user-supplied code).
Missing right curly or square bracket at (user-supplied code), within string
syntax error at (user-supplied code), at EOF


Any suggestions using "rename" command?










share|improve this question
























  • You're trying to stuff the shell variable expansion $_##.* into perl.

    – glenn jackman
    Mar 5 at 21:08













0












0








0








I want to rename files with zero padded numbers while keeping extension.

Example

a.abc

b.cde

c.xyz



to be renamed as

001.abc

002.cde

003.xyz



:~/x$ rename -n -v 's/.+/our $i; sprintf("%03d.jpg", 1+$i++)/e' *
#output>
rename(a.abc, 001.jpg)
rename(b.cde, 002.jpg)
rename(c.xyz, 003.jpg)
#then
:~/x$ echo "a.abc"
a.abc
:~/x$ echo $_##*.
#output>
abc
so I tried>
:~/x$ rename -n -v 's/.+/our $i; sprintf("%03d.$_##*.", 1+$i++)/' *
Global symbol "$i" requires explicit package name (did you forget to declare "my $i"?) at (user-supplied code).
Missing right curly or square bracket at (user-supplied code), within string
syntax error at (user-supplied code), at EOF


Any suggestions using "rename" command?










share|improve this question
















I want to rename files with zero padded numbers while keeping extension.

Example

a.abc

b.cde

c.xyz



to be renamed as

001.abc

002.cde

003.xyz



:~/x$ rename -n -v 's/.+/our $i; sprintf("%03d.jpg", 1+$i++)/e' *
#output>
rename(a.abc, 001.jpg)
rename(b.cde, 002.jpg)
rename(c.xyz, 003.jpg)
#then
:~/x$ echo "a.abc"
a.abc
:~/x$ echo $_##*.
#output>
abc
so I tried>
:~/x$ rename -n -v 's/.+/our $i; sprintf("%03d.$_##*.", 1+$i++)/' *
Global symbol "$i" requires explicit package name (did you forget to declare "my $i"?) at (user-supplied code).
Missing right curly or square bracket at (user-supplied code), within string
syntax error at (user-supplied code), at EOF


Any suggestions using "rename" command?







command-line rename






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 5 at 17:56







Vijay

















asked Mar 5 at 17:30









VijayVijay

1034




1034












  • You're trying to stuff the shell variable expansion $_##.* into perl.

    – glenn jackman
    Mar 5 at 21:08

















  • You're trying to stuff the shell variable expansion $_##.* into perl.

    – glenn jackman
    Mar 5 at 21:08
















You're trying to stuff the shell variable expansion $_##.* into perl.

– glenn jackman
Mar 5 at 21:08





You're trying to stuff the shell variable expansion $_##.* into perl.

– glenn jackman
Mar 5 at 21:08










2 Answers
2






active

oldest

votes


















2














rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/[^.]*/$zn/' *


This would probably do what you intended. Instead of putting the Perl code inside the substitution, we run it before the substitution.



The regular expression [^.]* would match any length string up to (but not including) the first dot in the filename.



To match up to the last dot, use .*. instead, and insert the dot on the replacement side:



rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/.*./$zn./' *


Note that this would also rename directories.




Alternatively, using a simple shell loop, assuming you would want to enumerate the files in the order they are expanded by the * shell glob, and that you use bash:



n=1
for filename in *; do
[ ! -f "$filename" ] && continue
zn=$( printf '%03d' "$n" )
mv -i -- "$filename" "$zn.$filename##*."
n=$(( n + 1 ))
done


This additionally skips any name that does not refer to a regular file (or a symbolic link to one). Apart from that, it follows very closely the Perl rename variation above in that it keeps a counter (n) and a zero-filled variant of the counter (zn).



The variable n is a simple counter, and $zn is has the same value as $n, but as a zero-filled three-digit number.



The value of $zn.$filename##*. would expand to the zero-filled number, followed by a dot and the final filename suffix of the original filename. If more than one dot is present in the original filename, everything up to the last dot will be replaced by the zero-filled number. Change ## to # to replace up to the first dot.



This assumes that you run the loop on files in the current directory only.






share|improve this answer




















  • 1





    @VeeJay Read again.

    – Kusalananda
    Mar 5 at 18:04






  • 1





    Sorry I was on mobile didn't read properly. Made my day.

    – Vijay
    Mar 5 at 18:50











  • Rename command-lines are perfect. Please check the mv cmd, it didn't work. Out put mv: overwrite '001.abc'? after first file.

    – Vijay
    Mar 5 at 18:58











  • @VeeJay Ah, thanks for that. I thought I simplified the code, but in fact I broke it. Now fixed.

    – Kusalananda
    Mar 5 at 19:17



















2














You could do



rename -n -v 'our $i; s^./.+?(.[^.]*)?zsprintf "%03d%s", ++$i, $1se' ./*



  • ./ prefix in ./*: needed for some variants of rename that would fail otherwise for filenames starting with -.


  • .+?: match at least one character, as we don't want a leading . (for hidden files, only relevant if the dotglob option of your shell is enabled) to be considered as an extension separator.


  • (.[^.]*)?: also rename files without extension (like .foo or foo)


  • z: match end of the subject. More generally with rename, you don't want to use $ as it matches either at the end of the subject or before a trailing newline.


  • s flag: make sure . also matches a newline character which is as valid as any in a file name.


  • e flag: the replacement is a perl expression, so we can use sprintf there.





share|improve this answer























    Your Answer








    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "106"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f504550%2frename-files-with-zero-padded-numbers-while-keeping-extension-using-rename-com%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/[^.]*/$zn/' *


    This would probably do what you intended. Instead of putting the Perl code inside the substitution, we run it before the substitution.



    The regular expression [^.]* would match any length string up to (but not including) the first dot in the filename.



    To match up to the last dot, use .*. instead, and insert the dot on the replacement side:



    rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/.*./$zn./' *


    Note that this would also rename directories.




    Alternatively, using a simple shell loop, assuming you would want to enumerate the files in the order they are expanded by the * shell glob, and that you use bash:



    n=1
    for filename in *; do
    [ ! -f "$filename" ] && continue
    zn=$( printf '%03d' "$n" )
    mv -i -- "$filename" "$zn.$filename##*."
    n=$(( n + 1 ))
    done


    This additionally skips any name that does not refer to a regular file (or a symbolic link to one). Apart from that, it follows very closely the Perl rename variation above in that it keeps a counter (n) and a zero-filled variant of the counter (zn).



    The variable n is a simple counter, and $zn is has the same value as $n, but as a zero-filled three-digit number.



    The value of $zn.$filename##*. would expand to the zero-filled number, followed by a dot and the final filename suffix of the original filename. If more than one dot is present in the original filename, everything up to the last dot will be replaced by the zero-filled number. Change ## to # to replace up to the first dot.



    This assumes that you run the loop on files in the current directory only.






    share|improve this answer




















    • 1





      @VeeJay Read again.

      – Kusalananda
      Mar 5 at 18:04






    • 1





      Sorry I was on mobile didn't read properly. Made my day.

      – Vijay
      Mar 5 at 18:50











    • Rename command-lines are perfect. Please check the mv cmd, it didn't work. Out put mv: overwrite '001.abc'? after first file.

      – Vijay
      Mar 5 at 18:58











    • @VeeJay Ah, thanks for that. I thought I simplified the code, but in fact I broke it. Now fixed.

      – Kusalananda
      Mar 5 at 19:17
















    2














    rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/[^.]*/$zn/' *


    This would probably do what you intended. Instead of putting the Perl code inside the substitution, we run it before the substitution.



    The regular expression [^.]* would match any length string up to (but not including) the first dot in the filename.



    To match up to the last dot, use .*. instead, and insert the dot on the replacement side:



    rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/.*./$zn./' *


    Note that this would also rename directories.




    Alternatively, using a simple shell loop, assuming you would want to enumerate the files in the order they are expanded by the * shell glob, and that you use bash:



    n=1
    for filename in *; do
    [ ! -f "$filename" ] && continue
    zn=$( printf '%03d' "$n" )
    mv -i -- "$filename" "$zn.$filename##*."
    n=$(( n + 1 ))
    done


    This additionally skips any name that does not refer to a regular file (or a symbolic link to one). Apart from that, it follows very closely the Perl rename variation above in that it keeps a counter (n) and a zero-filled variant of the counter (zn).



    The variable n is a simple counter, and $zn is has the same value as $n, but as a zero-filled three-digit number.



    The value of $zn.$filename##*. would expand to the zero-filled number, followed by a dot and the final filename suffix of the original filename. If more than one dot is present in the original filename, everything up to the last dot will be replaced by the zero-filled number. Change ## to # to replace up to the first dot.



    This assumes that you run the loop on files in the current directory only.






    share|improve this answer




















    • 1





      @VeeJay Read again.

      – Kusalananda
      Mar 5 at 18:04






    • 1





      Sorry I was on mobile didn't read properly. Made my day.

      – Vijay
      Mar 5 at 18:50











    • Rename command-lines are perfect. Please check the mv cmd, it didn't work. Out put mv: overwrite '001.abc'? after first file.

      – Vijay
      Mar 5 at 18:58











    • @VeeJay Ah, thanks for that. I thought I simplified the code, but in fact I broke it. Now fixed.

      – Kusalananda
      Mar 5 at 19:17














    2












    2








    2







    rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/[^.]*/$zn/' *


    This would probably do what you intended. Instead of putting the Perl code inside the substitution, we run it before the substitution.



    The regular expression [^.]* would match any length string up to (but not including) the first dot in the filename.



    To match up to the last dot, use .*. instead, and insert the dot on the replacement side:



    rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/.*./$zn./' *


    Note that this would also rename directories.




    Alternatively, using a simple shell loop, assuming you would want to enumerate the files in the order they are expanded by the * shell glob, and that you use bash:



    n=1
    for filename in *; do
    [ ! -f "$filename" ] && continue
    zn=$( printf '%03d' "$n" )
    mv -i -- "$filename" "$zn.$filename##*."
    n=$(( n + 1 ))
    done


    This additionally skips any name that does not refer to a regular file (or a symbolic link to one). Apart from that, it follows very closely the Perl rename variation above in that it keeps a counter (n) and a zero-filled variant of the counter (zn).



    The variable n is a simple counter, and $zn is has the same value as $n, but as a zero-filled three-digit number.



    The value of $zn.$filename##*. would expand to the zero-filled number, followed by a dot and the final filename suffix of the original filename. If more than one dot is present in the original filename, everything up to the last dot will be replaced by the zero-filled number. Change ## to # to replace up to the first dot.



    This assumes that you run the loop on files in the current directory only.






    share|improve this answer















    rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/[^.]*/$zn/' *


    This would probably do what you intended. Instead of putting the Perl code inside the substitution, we run it before the substitution.



    The regular expression [^.]* would match any length string up to (but not including) the first dot in the filename.



    To match up to the last dot, use .*. instead, and insert the dot on the replacement side:



    rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/.*./$zn./' *


    Note that this would also rename directories.




    Alternatively, using a simple shell loop, assuming you would want to enumerate the files in the order they are expanded by the * shell glob, and that you use bash:



    n=1
    for filename in *; do
    [ ! -f "$filename" ] && continue
    zn=$( printf '%03d' "$n" )
    mv -i -- "$filename" "$zn.$filename##*."
    n=$(( n + 1 ))
    done


    This additionally skips any name that does not refer to a regular file (or a symbolic link to one). Apart from that, it follows very closely the Perl rename variation above in that it keeps a counter (n) and a zero-filled variant of the counter (zn).



    The variable n is a simple counter, and $zn is has the same value as $n, but as a zero-filled three-digit number.



    The value of $zn.$filename##*. would expand to the zero-filled number, followed by a dot and the final filename suffix of the original filename. If more than one dot is present in the original filename, everything up to the last dot will be replaced by the zero-filled number. Change ## to # to replace up to the first dot.



    This assumes that you run the loop on files in the current directory only.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Mar 5 at 19:17

























    answered Mar 5 at 17:46









    KusalanandaKusalananda

    139k17259430




    139k17259430







    • 1





      @VeeJay Read again.

      – Kusalananda
      Mar 5 at 18:04






    • 1





      Sorry I was on mobile didn't read properly. Made my day.

      – Vijay
      Mar 5 at 18:50











    • Rename command-lines are perfect. Please check the mv cmd, it didn't work. Out put mv: overwrite '001.abc'? after first file.

      – Vijay
      Mar 5 at 18:58











    • @VeeJay Ah, thanks for that. I thought I simplified the code, but in fact I broke it. Now fixed.

      – Kusalananda
      Mar 5 at 19:17













    • 1





      @VeeJay Read again.

      – Kusalananda
      Mar 5 at 18:04






    • 1





      Sorry I was on mobile didn't read properly. Made my day.

      – Vijay
      Mar 5 at 18:50











    • Rename command-lines are perfect. Please check the mv cmd, it didn't work. Out put mv: overwrite '001.abc'? after first file.

      – Vijay
      Mar 5 at 18:58











    • @VeeJay Ah, thanks for that. I thought I simplified the code, but in fact I broke it. Now fixed.

      – Kusalananda
      Mar 5 at 19:17








    1




    1





    @VeeJay Read again.

    – Kusalananda
    Mar 5 at 18:04





    @VeeJay Read again.

    – Kusalananda
    Mar 5 at 18:04




    1




    1





    Sorry I was on mobile didn't read properly. Made my day.

    – Vijay
    Mar 5 at 18:50





    Sorry I was on mobile didn't read properly. Made my day.

    – Vijay
    Mar 5 at 18:50













    Rename command-lines are perfect. Please check the mv cmd, it didn't work. Out put mv: overwrite '001.abc'? after first file.

    – Vijay
    Mar 5 at 18:58





    Rename command-lines are perfect. Please check the mv cmd, it didn't work. Out put mv: overwrite '001.abc'? after first file.

    – Vijay
    Mar 5 at 18:58













    @VeeJay Ah, thanks for that. I thought I simplified the code, but in fact I broke it. Now fixed.

    – Kusalananda
    Mar 5 at 19:17






    @VeeJay Ah, thanks for that. I thought I simplified the code, but in fact I broke it. Now fixed.

    – Kusalananda
    Mar 5 at 19:17














    2














    You could do



    rename -n -v 'our $i; s^./.+?(.[^.]*)?zsprintf "%03d%s", ++$i, $1se' ./*



    • ./ prefix in ./*: needed for some variants of rename that would fail otherwise for filenames starting with -.


    • .+?: match at least one character, as we don't want a leading . (for hidden files, only relevant if the dotglob option of your shell is enabled) to be considered as an extension separator.


    • (.[^.]*)?: also rename files without extension (like .foo or foo)


    • z: match end of the subject. More generally with rename, you don't want to use $ as it matches either at the end of the subject or before a trailing newline.


    • s flag: make sure . also matches a newline character which is as valid as any in a file name.


    • e flag: the replacement is a perl expression, so we can use sprintf there.





    share|improve this answer



























      2














      You could do



      rename -n -v 'our $i; s^./.+?(.[^.]*)?zsprintf "%03d%s", ++$i, $1se' ./*



      • ./ prefix in ./*: needed for some variants of rename that would fail otherwise for filenames starting with -.


      • .+?: match at least one character, as we don't want a leading . (for hidden files, only relevant if the dotglob option of your shell is enabled) to be considered as an extension separator.


      • (.[^.]*)?: also rename files without extension (like .foo or foo)


      • z: match end of the subject. More generally with rename, you don't want to use $ as it matches either at the end of the subject or before a trailing newline.


      • s flag: make sure . also matches a newline character which is as valid as any in a file name.


      • e flag: the replacement is a perl expression, so we can use sprintf there.





      share|improve this answer

























        2












        2








        2







        You could do



        rename -n -v 'our $i; s^./.+?(.[^.]*)?zsprintf "%03d%s", ++$i, $1se' ./*



        • ./ prefix in ./*: needed for some variants of rename that would fail otherwise for filenames starting with -.


        • .+?: match at least one character, as we don't want a leading . (for hidden files, only relevant if the dotglob option of your shell is enabled) to be considered as an extension separator.


        • (.[^.]*)?: also rename files without extension (like .foo or foo)


        • z: match end of the subject. More generally with rename, you don't want to use $ as it matches either at the end of the subject or before a trailing newline.


        • s flag: make sure . also matches a newline character which is as valid as any in a file name.


        • e flag: the replacement is a perl expression, so we can use sprintf there.





        share|improve this answer













        You could do



        rename -n -v 'our $i; s^./.+?(.[^.]*)?zsprintf "%03d%s", ++$i, $1se' ./*



        • ./ prefix in ./*: needed for some variants of rename that would fail otherwise for filenames starting with -.


        • .+?: match at least one character, as we don't want a leading . (for hidden files, only relevant if the dotglob option of your shell is enabled) to be considered as an extension separator.


        • (.[^.]*)?: also rename files without extension (like .foo or foo)


        • z: match end of the subject. More generally with rename, you don't want to use $ as it matches either at the end of the subject or before a trailing newline.


        • s flag: make sure . also matches a newline character which is as valid as any in a file name.


        • e flag: the replacement is a perl expression, so we can use sprintf there.






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Mar 5 at 20:13









        Stéphane ChazelasStéphane Chazelas

        312k57592948




        312k57592948



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f504550%2frename-files-with-zero-padded-numbers-while-keeping-extension-using-rename-com%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown






            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay