<p>What is the best way, using Bash, to rename files in the form:</p>

<pre><code>(foo1, foo2, ..., foo1300, ..., fooN)
</code></pre>

<p>With zero-padded file names:</p>

<pre><code>(foo00001, foo00002, ..., foo01300, ..., fooN)
</code></pre>

[{'answer_id': 55775, 'author': 'dF.', 'author_id': 3002, 'author_profile': 'https://Stackoverflow.com/users/3002', 'pm_score': 2, 'selected': False, 'text': '<p>The following will do it:</p>\n\n<pre><code>for ((i=1; i&lt;=N; i++)) ; do mv foo$i `printf foo%05d $i` ; done\n</code></pre>\n\n<p><strong>EDIT:</strong> changed to use ((i=1,...)), thanks <a href="https://stackoverflow.com/users/4285/mweerden">mweerden</a>!</p>\n'}, {'answer_id': 55778, 'author': 'amrox', 'author_id': 4468, 'author_profile': 'https://Stackoverflow.com/users/4468', 'pm_score': 0, 'selected': False, 'text': '<p>Here\'s a quick solution that assumes a fixed length prefix (your "foo") and fixed length padding.  If you need more flexibility, maybe this will at least be a helpful starting point.</p>\n\n<pre><code>#!/bin/bash\n\n# some test data\nfiles="foo1\nfoo2\nfoo100\nfoo200\nfoo9999"\n\nfor f in $files; do\n    prefix=`echo "$f" | cut -c 1-3`        # chars 1-3 = "foo"\n    number=`echo "$f" | cut -c 4-`         # chars 4-end = the number\n    printf "%s%04d\\n" "$prefix" "$number"\ndone\n</code></pre>\n'}, {'answer_id': 55782, 'author': 'Chris Conway', 'author_id': 1412, 'author_profile': 'https://Stackoverflow.com/users/1412', 'pm_score': 6, 'selected': True, 'text': "<p>In case <code>N</code> is not a priori fixed:</p>\n<pre><code>for f in foo[0-9]*; do\n  mv &quot;$f&quot; &quot;$(printf 'foo%05d' &quot;${f#foo}&quot;)&quot;\ndone\n</code></pre>\n"}, {'answer_id': 506377, 'author': 'Fritz G. Mehner', 'author_id': 57457, 'author_profile': 'https://Stackoverflow.com/users/57457', 'pm_score': 3, 'selected': False, 'text': "<p>Pure Bash, no external processes other than 'mv':</p>\n\n<pre><code>for file in foo*; do\n  newnumber='00000'${file#foo}      # get number, pack with zeros\n  newnumber=${newnumber:(-5)}       # the last five characters\n  mv $file foo$newnumber            # rename\ndone\n</code></pre>\n"}, {'answer_id': 3700146, 'author': 'Michael Baltaks', 'author_id': 23312, 'author_profile': 'https://Stackoverflow.com/users/23312', 'pm_score': 4, 'selected': False, 'text': '<p>I had a more complex case where the file names had a postfix as well as a prefix. I also needed to perform a subtraction on the number from the filename.</p>\n\n<p>For example, I wanted <code>foo56.png</code> to become <code>foo00000055.png</code>.</p>\n\n<p>I hope this helps if you\'re doing something more complex.</p>\n\n<pre><code>#!/bin/bash\n\nprefix="foo"\npostfix=".png"\ntargetDir="../newframes"\npaddingLength=8\n\nfor file in ${prefix}[0-9]*${postfix}; do\n  # strip the prefix off the file name\n  postfile=${file#$prefix}\n  # strip the postfix off the file name\n  number=${postfile%$postfix}\n  # subtract 1 from the resulting number\n  i=$((number-1))\n  # copy to a new name with padded zeros in a new folder\n  cp ${file} "$targetDir"/$(printf $prefix%0${paddingLength}d$postfix $i)\ndone\n</code></pre>\n'}, {'answer_id': 4561801, 'author': 'KARASZI István', 'author_id': 221213, 'author_profile': 'https://Stackoverflow.com/users/221213', 'pm_score': 6, 'selected': False, 'text': "<p>It's not pure bash, but much easier with the Perl version of <code>rename</code>:</p>\n<pre><code>rename 's/\\d+/sprintf(&quot;%05d&quot;,$&amp;)/e' foo*\n</code></pre>\n<p>Where <code>'s/\\d+/sprintf(&quot;%05d&quot;,$&amp;)/e'</code> is the Perl replace regular expression.</p>\n<ul>\n<li><code>\\d+</code> will match the first set of numbers (at least one number)</li>\n<li><code>sprintf(&quot;%05d&quot;,$&amp;)</code> will pass the matched numbers to Perl's <code>sprintf</code>, and <code>%05d</code> will pad to five digits</li>\n</ul>\n"}, {'answer_id': 45569550, 'author': 'Pioz', 'author_id': 302005, 'author_profile': 'https://Stackoverflow.com/users/302005', 'pm_score': 3, 'selected': False, 'text': '<p>The oneline command that I use is this:</p>\n\n<pre><code>ls * | cat -n | while read i f; do mv "$f" `printf "PATTERN" "$i"`; done\n</code></pre>\n\n<p>PATTERN can be for example:</p>\n\n<ul>\n<li>rename with increment counter: <code>%04d.${f#*.}</code> (keep original file extension)</li>\n<li>rename with increment counter with prefix: <code>photo_%04d.${f#*.}</code> (keep original extension)</li>\n<li>rename with increment counter and change extension to jpg: <code>%04d.jpg</code></li>\n<li>rename with increment counter with prefix and file basename: <code>photo_$(basename $f .${f#*.})_%04d.${f#*.}</code></li>\n<li>...</li>\n</ul>\n\n<p>You can filter the file to rename with for example <code>ls *.jpg | ...</code></p>\n\n<p>You have available the variable <code>f</code> that is the file name and <code>i</code> that is the counter.</p>\n\n<p>For your question the right command is:</p>\n\n<pre><code>ls * | cat -n | while read i f; do mv "$f" `printf "foo%d05" "$i"`; done\n</code></pre>\n'}, {'answer_id': 54888706, 'author': 'AntonAL', 'author_id': 235158, 'author_profile': 'https://Stackoverflow.com/users/235158', 'pm_score': 1, 'selected': False, 'text': '<p>My solution replaces numbers, <strong>everywhere in a string</strong></p>\n\n<pre class="lang-sh prettyprint-override"><code>for f in * ; do\n    number=`echo $f | sed \'s/[^0-9]*//g\'`\n    padded=`printf "%04d" $number`\n    echo $f | sed "s/${number}/${padded}/";\ndone\n</code></pre>\n\n<p>You can easily try it, since it just prints transformed file names (no filesystem operations are performed).</p>\n\n<h2>Explanation:</h2>\n\n<h3>Looping through list of files</h3>\n\n<p>A loop: <code>for f in * ; do ;done</code>, lists all files and passes each filename as <code>$f</code> variable to loop body.</p>\n\n<h3>Grabbing the number from string</h3>\n\n<p>With <code>echo $f | sed</code> we pipe variable <code>$f</code> to <code>sed</code> program.</p>\n\n<p>In command <code>sed \'s/[^0-9]*//g\'</code>, part <code>[^0-9]*</code> with modifier <code>^</code> tells to match opposite from digit 0-9 (not a number) and then remove it it with empty replacement <code>//</code>. Why not just remove <code>[a-z]</code>? Because filename can contain dots, dashes etc. So, we strip everything, that is not a number and get a number.</p>\n\n<p>Next, we assign the result to <code>number</code> variable. Remember to not put spaces in assignment, like <code>number = …</code>, because you get different behavior.</p>\n\n<p>We assign execution result of a command to variable, wrapping the command with backtick symbols `.</p>\n\n<h3>Zero padding</h3>\n\n<p>Command <code>printf "%04d" $number</code> changes format of a number to 4 digits and adds zeros if our number contains less than 4 digits.</p>\n\n<h3>Replacing number to zero-padded number</h3>\n\n<p>We use <code>sed</code> again with replacement command like <code>s/substring/replacement/</code>. To interpret our variables, we use double quotes and substitute our variables in this way <code>${number}</code>.</p>\n\n<hr>\n\n<p>The script above just prints transformed names, so, let\'s do actual renaming job:</p>\n\n<pre><code>for f in *.js ; do\n    number=`echo $f | sed \'s/[^0-9]*//g\'`\n    padded=`printf "%04d" $number`\n    new_name=`echo $f | sed "s/${number}/${padded}/"`\n    mv $f $new_name;\ndone\n</code></pre>\n\n<p>Hope this helps someone.</p>\n\n<p>I spent several hours to figure this out.</p>\n'}, {'answer_id': 55409116, 'author': 'Victoria Stuart', 'author_id': 1904943, 'author_profile': 'https://Stackoverflow.com/users/1904943', 'pm_score': 3, 'selected': False, 'text': '<p>To left-pad numbers in filenames:</p>\n\n<pre class="lang-sh prettyprint-override"><code>$ ls -l\ntotal 0\n-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010\n-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050\n-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 050.zzz\n-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10\n-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 1.zzz\n\n$ for f in [0-9]*.[a-z]*; do tmp=`echo $f | awk -F. \'{printf "%04d.%s\\n", $1, $2}\'`; mv "$f" "$tmp"; done;\n\n$ ls -l\ntotal 0\n-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0001.zzz\n-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0050.zzz\n-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010\n-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050\n-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10\n</code></pre>\n\n<p><strong>Explanation</strong></p>\n\n<pre class="lang-sh prettyprint-override"><code>for f in [0-9]*.[a-z]*; do tmp=`echo $f | \\\nawk -F. \'{printf "%04d.%s\\n", $1, $2}\'`; mv "$f" "$tmp"; done;\n</code></pre>\n\n<ul>\n<li>note the backticks: <code>`echo ... $2}\\`</code>  (The backslash, \\, immediately above just splits that one-liner over two lines for readability)</li>\n<li>in a loop find files that are named as numbers with lowercase alphabet extensions: <code>[0-9]*.[a-z]*</code></li>\n<li>echo that filename (<code>$f</code>) to pass it to <code>awk</code></li>\n<li><code>-F.</code> : <code>awk</code> field separator, a period (<code>.</code>): if matched, separates the file names as two fields (<code>$1</code> = number; <code>$2</code> = extension)</li>\n<li>format with <code>printf</code>: print first field (<code>$1</code>, the number part) as 4 digits (<code>%04d</code>), then print the period, then print the second field (<code>$2</code>: the extension) as a string (<code>%s</code>).  All of that is assigned to the <code>$tmp</code> variable</li>\n<li>lastly, move the source file (<code>$f</code>) to the new filename (<code>$tmp</code>)</li>\n</ul>\n'}, {'answer_id': 69038695, 'author': 'danday74', 'author_id': 1205871, 'author_profile': 'https://Stackoverflow.com/users/1205871', 'pm_score': 1, 'selected': False, 'text': "<p>This answer is derived from Chris Conway's accepted answer but <strong>assumes your files have an extension</strong> (unlike Chris' answer). Just paste this (rather long) one liner into your command line.</p>\n<pre><code>for f in foo[0-9]*; do mv &quot;$f&quot; &quot;$(printf 'foo%05d' &quot;${f#foo}&quot; 2&gt; /dev/null)&quot;; done; for f in foo[0-9]*; do mv &quot;$f&quot; &quot;$f.ext&quot;; done;\n</code></pre>\n<p><strong>OPTIONAL ADDITIONAL INFO</strong></p>\n<p>This script will rename</p>\n<pre><code>foo1.ext    &gt; foo00001.ext\nfoo2.ext    &gt; foo00002.ext\nfoo1300.ext &gt; foo01300.ext\n</code></pre>\n<p>To test it on your machine, just paste this one liner into an <strong>EMPTY</strong> directory.</p>\n<pre><code>rm * 2&gt; /dev/null; touch foo1.ext foo2.ext foo1300.ext; for f in foo[0-9]*; do mv &quot;$f&quot; &quot;$(printf 'foo%05d' &quot;${f#foo}&quot; 2&gt; /dev/null)&quot;; done; for f in foo[0-9]*; do mv &quot;$f&quot; &quot;$f.ext&quot;; done;\n</code></pre>\n<p>This deletes the content of the directory, creates the files in the above example and then does the batch rename.</p>\n<p>For those who don't need a one liner, the script indented looks like this.</p>\n<pre><code>for f in foo[0-9]*;\n  do mv &quot;$f&quot; &quot;$(printf 'foo%05d' &quot;${f#foo}&quot; 2&gt; /dev/null)&quot;;\ndone;\n\nfor f in foo[0-9]*;\n  do mv &quot;$f&quot; &quot;$f.ext&quot;;\ndone;\n</code></pre>\n"}]
['https://Stackoverflow.com/questions/55754', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/3020/']