<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://powershell.com/cs/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results for 'app:weblogs' matching tags 'ScriptBlock' and 'golden rule'</title><link>http://powershell.com/cs/search/SearchResults.aspx?q=app:weblogs&amp;tag=ScriptBlock,golden+rule&amp;orTags=0&amp;o=DateDescending</link><description>Search results for 'app:weblogs' matching tags 'ScriptBlock' and 'golden rule'</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><item><title>Renaming Files Puzzle - And Three Golden PowerShell Rules</title><link>http://powershell.com/cs/blogs/tobias/archive/2011/05/23/renaming-files-puzzle-and-three-golden-powershell-rules.aspx</link><pubDate>Mon, 23 May 2011 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:10492</guid><dc:creator>Tobias</dc:creator><description>&lt;p&gt;I am moderator for one of our &lt;a target="_blank" href="http://powershell.com/cs/forums/200.aspx"&gt;Ask-the-Experts forums&lt;/a&gt;, and every once in a while, I get questions I would like to discuss. Like this one:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;&amp;quot;I am tring to write a quick interactive command that will rename all the jpgs in the current directory and came up with the following command:&lt;br /&gt;&lt;br /&gt;$i=1; gci | ? { ($_.Extension -eq &amp;quot;.JPG&amp;quot;) -and !($_.Name.StartsWith(&amp;quot;cover&amp;quot;)) } | % { Rename-Item -Path &amp;quot;.\$_&amp;quot; -NewName [string]::Format(&amp;quot;picture_$i.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;div id=":1dv"&gt;&lt;em&gt;&lt;strong&gt;jpg&amp;quot;); $i++ }&lt;br /&gt;&lt;br /&gt;There appears to be a parameter binding issue. But the 2 parameters I have specified (-Path and -NewName) I have named so I assumed that position is not of relevance. What am I missing here?&amp;quot;&lt;/strong&gt;&lt;/em&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;Let&amp;#39;s see how we can solve this puzzle and come up with an easy solution using the&amp;nbsp;&amp;quot;3 Golden PowerShell rules&amp;quot;!&lt;/p&gt;
&lt;h2&gt;Think PowerShell! Use Parameters!&lt;/h2&gt;
&lt;div&gt;
&lt;p&gt;Whenever you work with files, &lt;strong&gt;Get-Childitem&lt;/strong&gt; (aka &lt;strong&gt;dir&lt;/strong&gt; or &lt;strong&gt;ls&lt;/strong&gt;) is your friend. And like most &lt;strong&gt;Get-*&lt;/strong&gt; cmdlets, it has a lot of parameters to help you get what you want. Of course you can always use &lt;strong&gt;Where-Object&lt;/strong&gt; (short: &lt;strong&gt;?&lt;/strong&gt;) to filter the results once you got them. That is only your last resort, though. Before you do that, always make sure the original cmdlet has no way of filtering. And &lt;strong&gt;Get-Childitem&lt;/strong&gt; has. So the first part would be selecting the files you want to rename like this:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Get-Childitem c:\somefolder -Filter cover*.jpg&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Another thing to watch out is this: never use &lt;strong&gt;Get-Childitem&lt;/strong&gt; without specifying an absolute or relative path to start with. Else, it will depend on your current path, and that path may change. So the next time you are running your code, it may no longer work because your current path is no longer pointing to the files you want to rename.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule #1:&lt;/strong&gt; Before you resort to &lt;strong&gt;Where-Object&lt;/strong&gt;, make sure the &lt;em&gt;upstream&lt;/em&gt; cmdlet has no built-in parameters to do the same! It is easier and much faster!&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Think PowerShell! Use Pipeline Binding!&lt;/h2&gt;
&lt;p&gt;The next thing is finding the right cmdlet for the action you want to take. &lt;strong&gt;Rename-Item&lt;/strong&gt; was the perfect choice. However, it is not necessary to use &lt;strong&gt;Foreach-Object&lt;/strong&gt; (short: &lt;strong&gt;%&lt;/strong&gt;) to iterate through all the files. Instead, &lt;strong&gt;Rename-Item&lt;/strong&gt; is able to accept the files directly via pipeline. &lt;strong&gt;Get-Help&lt;/strong&gt; can tell you that:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Get-Help -Name Rename-Item -Parameter Path&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It returns: &lt;em&gt;Accept pipeline input?&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; true (ByValue, ByPropertyName) &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So the second part of the solution looks like this:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Get-Childitem c:\somefolder -Filter cover*.jpg | Rename-Item -NewName &amp;quot;somenewname.jpg&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule #2:&lt;/strong&gt; Before you resport to &lt;strong&gt;Foreach-Object&lt;/strong&gt;, make sure the &lt;em&gt;downstream&lt;/em&gt; cmdlet cannot receive your results via pipeline!&lt;/p&gt;
&lt;h2&gt;Think PowerShell! Use Scriptblocks!&lt;/h2&gt;
&lt;p&gt;Of course, renaming a bunch of files to the exact same name will fail, and thus you may be intrigued to use a &lt;strong&gt;foreach-object&lt;/strong&gt; loop after all so you can compose individual file names. But that is not necessary. Many cmdlets accept &lt;strong&gt;scriptblocks&lt;/strong&gt; which resemble executable code, so rather than submitting a fixed name, submit code that composes the name. The final solution looks like this:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;$global:i = 1; dir c:\test1\ -filter cover*.bmp | rename-item -NewName { &amp;quot;picture_$i.jpg&amp;quot;; $global:i++}&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This line will rename all jpg files that start with &amp;quot;cover&amp;quot; in folder c:\test1 to pictureX.jpg where X is an incrementing index number.&lt;/p&gt;
&lt;p&gt;Note the use of &lt;strong&gt;global:&lt;/strong&gt;&amp;nbsp; (you could also use &lt;strong&gt;script:&lt;/strong&gt;). With this prefix, you tell PowerShell to use the same variable. If you omitted that, incrementing $i inside the scriptblock would not have an effect on the global variable $i, because inside a script block, the variable is local and would be discarded each time after the script block was done.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule #3:&lt;/strong&gt;&amp;nbsp;Before you design complex code to calculate results for parameters, make sure the parameters do not accept scriptblocks in the first place.&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;Admittedly, this third rule is not that easy to follow because there is no easy way to know whether a parameter can actually receive a script block. &lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Hope to see you next week,&lt;/p&gt;
&lt;p&gt;Tobias&lt;/p&gt;
&lt;p&gt;Microsoft MVP PowerShell Germany&lt;/p&gt;
&lt;p&gt;P.S.&lt;br /&gt;If you live in Germany or other parts of Europe and your company would like to set up a truly great PowerShell training, just contact me! I regularly train mid- to large-size companies. Trainings are always a blast with tons of real-world-examples and solutions. Here&amp;#39;s how to get in touch with me: &lt;a href="mailto:tobias.weltner@scriptinternals.de"&gt;&lt;span style="color:#3366cc;"&gt;tobias.weltner@scriptinternals.de&lt;/span&gt;&lt;/a&gt;&amp;nbsp; &lt;/p&gt;
&lt;/div&gt;</description></item></channel></rss>