title: In shell scripting, what's the difference between $i, %i and %%i?
body: <p>I was trying to prepend a string to the filename of a bunch of files. I read through several questions and all of them recommended different syntax for basically the same command, only one of which worked.</p>
  
  <p>I'm using <a href="https://cmder.net/" rel="nofollow noreferrer">cmder</a> as my console. I was trying to prepend <code>crypto-</code> to all files in the CWD and here's what I tried:</p>
  
  <p><a href="https://stackoverflow.com/a/602770/3130281">This answer</a> recommended a syntax like:</p>
  
  <pre><code>for i in *.png ; do mv "$i" "crypto-$i" ; done
  </code></pre>
  
  <blockquote>
    <p>i was unexpected at this time.</p>
  </blockquote>
  
  <hr>
  
  <p><a href="https://stackoverflow.com/a/13740064/3130281">This answer</a> recommended a double percent sign <code>%%i</code>:</p>
  
  <pre><code>for %%i in *.png ; do mv "$i" "crypto-$i" ; done
  </code></pre>
  
  <blockquote>
    <p>%%i was unexpected at this time.</p>
  </blockquote>
  
  <hr>
  
  <p><a href="https://stackoverflow.com/a/8898432/3130281">This answer</a> recommended a single percent sign instead of dollar sign for <code>i</code>:</p>
  
  <pre><code>for %i in *.png ; do mv "$i" "crypto-$i" ; done
  </code></pre>
  
  <blockquote>
    <p>*.png was unexpected at this time.</p>
  </blockquote>
  
  <p>I got further this time and noticed that in the answer, the filename was enclosed in brackets, so I tried:</p>
  
  <pre><code>for %i in (*.png) ; do mv "$i" "crypto-$i" ; done
  </code></pre>
  
  <blockquote>
    <p>mv "$i" "crypto-$i" ; done<br>
    mv: target 'done' is not a directory</p>
  </blockquote>
  
  <p>Then I figured that the command should also be in brackets:</p>
  
  <pre><code>for %i in (*.png) ; do (mv "$i" "crypto-$i") ; done
  </code></pre>
  
  <blockquote>
    <p>done was unexpected at this time.</p>
  </blockquote>
  
  <p>After that, I decided to try without <code>;</code>:</p>
  
  <pre><code>for %i in (*.png) do (mv "$i" "crypto-$i")
  </code></pre>
  
  <blockquote>
    <p>(mv "$i" "crypto-$i" )<br>
    mv: cannot stat '$i': No such file or directory</p>
  </blockquote>
  
  <p>And finally, I thought that since I used <code>%</code> to refer to <code>i</code> the first time, I should use <code>%</code> again later on and tried:</p>
  
  <pre><code>for %i in (*.png) do (mv "%i" "crypto-%i")
  </code></pre>
  
  <p>This variant worked and all files were renamed successfully.</p>
  
  <hr>
  
  <p>My question is - why did the last command work and the others didn't? Why are there so many different syntaxes that appear to work only in certain occasions? What are those occasions? Why do you put brackets sometimes and sometimes not? Why do you put semicolons sometimes and sometimes not? What's the difference between <code>$i</code>, <code>%i</code> and <code>%%i</code>?</p>