Look Ma, I’m using PowerShell

Why?

Couple of days ago I’ve decided to filter some of my music and upload it to my HTC HD2. I was using Windows Media Player (WMP) for that. I haven’t noticed that WMP converted all uploaded songs to WMA. Problem was that many of uploaded files were unable to play on my phone (neither by using HTC Player nor WMMP). I decided to upload all my favorite songs (ones I’ve already filtered before) one more time but this time directly to my MicroSD card as MP3. The worst thing was that I haven’t all my filtered songs (well just the ones in WMA and that’s not what I need). What makes it more complicated is that many of my songs ware stored as FLACs on my HDD, therefore I would need to convert them manually to. I couldn’t call myself an IT guy if I wouldn’t come up with idea to write a script to automatize entire process of filtering, converting and copying all songs I want to have on my phone to one place.

So, PowerShell?

Since I’ve already had an idea what I want to accomplish, I’ve decided to make it even more funny (geeky funny) and useful. I’ve tried many scripting languages before: <a href="http://en.wikipedia.org/wiki/Python_%28programming_language%29" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://en .wikipedia.org/wiki/Python_%28programming_language%29′, ‘Python’);”>Python, Bash, Batch, Perl and PHP (this one for good) so this time I’ve decided to try PowerShell. Basically, PowerShell is way (way way) more advanced command line shell for Windows. I’ve heard about it before (it would be shame if I wouldn’t) but I’ve had never tried it before so I though it would be a good chance to do that. Especially when I’m working as computer administrator currently and I might need PowerShell at my work to speed things up.

130 lines of something

So, I’ve opened PowerShell ISE, start trying things out, did a lot of searching and reading and finally (after almost 5 hours) I’ve came up with the result you can see at the end of the post. The final script does what I’ve wanted:

  • Script loops though the WMA files I already have
  • For each WMA file it tries to find original FLAC/MP3 file
  • If the original file is in MP3 script simple copies it to destination directory (the one I’m going to upload to my phone)
  • If the original file is in FLAC, there’s more stuff we need to do:
    • Script extracts ID3 tags from the FLAC file
    • Saves cover from the FLAC file to the file with the dummy extension
    • While using ImageMagick, we determinate the correct mime-type of the cover image (since we don’t know it when exporting from FLAC) and rename cover to filename with correct extension (if extension is incorrect, LAME will fail to load it)
    • We resize cover image (with the same ImageMagick) to 256×256 to minimize size of large cover images since LAME has cover file size limit
    • We convert FLAC file to WAV (since we cannot convert from FLAC to MP3 directly)
    • From WAV we can convert file to MP3. While doing that, we also apply all available ID3 tags.
    • Copy new MP3 file to destination directory.
  • If everything completed successfully we add .done extension to WMA file so we know that we have this file as MP3 in our destination directory. It also let me to check for failed files (ones without .done extension) and convert/copy them manually

So, that’s what I’ve managed to do. I ain’t gonna comment every (any) line of code. Feel free to do that in comments.

Conclusions

Well, I’m sure I could do that job manually in about 1-2 hours while I spend much more time while writing this script. Anyhow, it was great experience and it would help a lot if I ever need to write something else in PowerShell. Though I’ve touched only small part of PowerShell itself, it looked to me pretty intuitive and not very complicated. Probably the hardest part was working with external executables (FLAC, LAME) and especially to process the errors of those commands (knowing if conversion succeeded or failed).

By the way, I’ve started reading “Windows PowerShell™ 2.0 Administrator’s Pocket Consultant” book from today so I help to improve my PowerShell knowledge and start using it more often.

Source and download

You can download this script from my SkyDrive here or see it below.

<br />
# Variables (might need to modify to work):<br />
$filenamesPath = 'D:MobileHTC HD2Music';<br />
$ltPath = 'D:\Music';<br />
$enPath = 'G:\MUSIC';<br />
$newPath = 'C:\Users\Tomas\Desktop\Music';<br />
$lameExePath = 'D:\Installs\Audio\Lame\lame.exe';<br />
$flacExePath = 'C:\Program Files (x86)\FLAC\flac.exe'<br />
$metaflacExePath = 'C:\Program Files (x86)\FLAC\metaflac.exe'<br />
$imageMagickPath = 'D:\Installs\Graphics\ImageMagick'<br />
$debug = $TRUE<br />
$erroractionpreference = &quot;SilentlyContinue&quot;<br />
$error.clear()</p>
<p># Function to convert the file<br />
function ConvertToMP3([string] $file)<br />
{<br />
    # Get FLAC tags:<br />
    $artist = (Invoke-Expression &quot;&amp; '$metaflacExePath' --show-tag=ARTIST `&quot;$file`&quot;&quot;) -Replace 'ARTIST=',''<br />
    $title = (Invoke-Expression &quot;&amp; '$metaflacExePath' --show-tag=TITLE `&quot;$file`&quot;&quot;) -Replace 'TITLE=',''<br />
    $album = (Invoke-Expression &quot;&amp; '$metaflacExePath' --show-tag=ALBUM `&quot;$file`&quot;&quot;) -Replace 'ALBUM=',''<br />
    $track = (Invoke-Expression &quot;&amp; '$metaflacExePath' --show-tag=TRACKNUMBER `&quot;$file`&quot;&quot;) -Replace 'TRACKNUMBER=',''<br />
    $genre = (Invoke-Expression &quot;&amp; '$metaflacExePath' --show-tag=GENRE `&quot;$file`&quot;&quot;) -Replace 'GENRE=',''<br />
    $year = (Invoke-Expression &quot;&amp; '$metaflacExePath' --show-tag=DATE `&quot;$file`&quot;&quot;) -Replace 'DATE=',''</p>
<p>    # Get cover:<br />
    $tmpCover = &quot;{0}folder.tmp&quot; -f $Env:Temp<br />
    Invoke-Expression &quot;&amp; '$metaflacExePath' --export-picture-to=`&quot;$tmpCover`&quot; `&quot;$file`&quot;&quot; | out-null<br />
    switch(Invoke-Expression &quot;D:InstallsGraphicsImageMagickidentify.exe  -format `&quot;%m`&quot; `&quot;$tmpCover`&quot;&quot;) {<br />
        &quot;JPEG&quot; { $extension = 'jpg' }<br />
        &quot;JPG&quot; { $extension = 'jpg' }<br />
        &quot;PNG&quot; { $extension = 'png' }<br />
        &quot;GIF&quot; { $extension = 'gif' }<br />
    }<br />
    $cover = &quot;{0}folder.{1}&quot; -f $Env:Temp,$extension<br />
    Invoke-Expression &quot;&amp; '$imageMagickPathconvert.exe' `&quot;$tmpCover`&quot; -resize 256x256!&gt; `&quot;$cover`&quot;&quot; | out-null<br />
    # Start conversion:<br />
    $wav = $file.Replace('.flac', '.wav');<br />
    Invoke-Expression &quot;&amp; '$flacExePath' -d -s -f `&quot;$file`&quot;&quot; | out-null<br />
    $toMP3 = &quot;&amp; '$lameExePath' -b 320 --vbr-new -V 0 -s 44.1 --id3v2-only `&quot;$wav`&quot; `&quot;$newPathtmp.mp3`&quot;&quot;<br />
    # Add ID3 tags if any:<br />
    if ($track -ne '') {<br />
        $toMP3 += &quot; --tn `&quot;$track`&quot;&quot;<br />
    }<br />
    if ($album -ne '') {<br />
        $toMP3 += &quot; --tl `&quot;$album`&quot;&quot;<br />
    }<br />
    if ($artist -ne '') {<br />
        $toMP3 += &quot; --ta `&quot;$artist`&quot;&quot;<br />
    }<br />
    if ($title -ne '') {<br />
        $toMP3 += &quot; --tt `&quot;$title`&quot;&quot;<br />
    }<br />
    if ($year -ne '') {<br />
        $toMP3 += &quot; --ty `&quot;$year`&quot;&quot;<br />
    }<br />
    if ($genre -ne '') {<br />
        $toMP3 += &quot; --tg `&quot;$genre`&quot;&quot;<br />
    }<br />
    if (Test-Path $cover) {<br />
        $toMP3 += &quot; --ti `&quot;$cover`&quot;&quot;<br />
    }<br />
    Invoke-Expression $toMP3<br />
    # Do some cleaning:<br />
    Remove-Item $tmpCover;<br />
    Remove-Item $cover;<br />
    Remove-Item $wav<br />
    if (Test-Path &quot;$newPathtmp.mp3&quot;) {<br />
        Rename-Item &quot;$newPathtmp.mp3&quot; -newName &quot;$artist - $title.mp3&quot;<br />
    }<br />
}</p>
<p># Clear previous output<br />
cls</p>
<p># Get list of current files:<br />
$currentFiles = Get-ChildItem $filenamesPath -recurse -include *.wma,*.mp3</p>
<p># Get list of available files:<br />
$ltFiles = Get-ChildItem $ltPath -recurse -include *.mp3,*.flac<br />
$enFiles = Get-ChildItem $enPath -recurse -include *.flac<br />
$availableFiles = $ltFiles + $enFiles;</p>
<p>$counter = 0;<br />
# Loop through every file we need to find:<br />
foreach ($filename in $currentFiles) {<br />
    $error.clear()<br />
    if($debug) {<br />
        Write-Host &quot;------------------------------------------------------------&quot;<br />
        Write-Host &quot;Searching for&quot;,$filename.Name,&quot;...&quot;<br />
    }<br />
    # Loop through every available file in the container<br />
    foreach ($file in $availableFiles) {<br />
        # Check if the file (without extensions) we're looking for matches the current one:<br />
        if ($filename.Name.Replace($filename.Extension,'') -eq $file.Name.Replace($file.extension,'')) {<br />
            if ($debug) {<br />
                Write-Host -Separator '' $filename.Name,&quot; found (&quot;,$file.Fullname,&quot;)&quot;<br />
            }<br />
            # Encode FLACs to MP3s:<br />
            if($file.extension -eq '.flac') {<br />
                if ($debug) {<br />
                    Write-Host 'Converting file',$file.Name,'to MP3...'<br />
                }<br />
                ConvertToMP3($file.Fullname)<br />
            } else {<br />
                # Simple copy file:<br />
                if ($debug) {<br />
                    Write-Host 'Copying file',$file.Name,'to',$newPath,'...'<br />
                }<br />
                Copy-Item $file.Fullname ($newPath + '' + ($file.Name -replace &quot;^d*?.s&quot;,&quot;&quot;))<br />
            }<br />
            # Increment the number of copied files and stop searching for current file since we already found one:<br />
            $counter++;<br />
            break<br />
        }<br />
    }<br />
    # Was there any errors:<br />
    if($error[0] -and !($error[0] -match 'ReplayGain')) {<br />
        if($debug) {<br />
           Write-Host 'Processing',$filename.Name,'failed'<br />
        }<br />
    }  else {<br />
        if($debug) {<br />
           Write-Host 'Processing',$filename.Name,'completed successfuly'<br />
        }<br />
        Rename-Item $filename.Fullname -newName ($filename.Name -replace $filename.Extension,($filename.Extension + &quot;.done&quot;))<br />
    }<br />
}<br />
if($debug) {<br />
    Write-Host $counter,'files founded';<br />
}<br />

Social

7 comments on the post

  1. Pingback: Count number of users who logged on to workstation in the last month (with Batch script) | Blog of Tomas Dabasinskas

  2. http://www.twojebiura.pl/nieznaczne-uchylenia
    Looking for a new or used automobile might be a challenging procedure unless you know what you are performing. By teaching yourself about automobile shopping prior to visit the dealer, you possibly can make issues much easier for yourself. The following tips will help your following store shopping trip be a little more pleasurable.

    Usually deliver a mechanic along when looking for a whole new vehicle. Auto retailers are well known for marketing lemons and you do not wish to be their following victim. Provided you can not get yourself a auto mechanic to look at autos along with you, at least make certain you have him evaluate your final selection prior to buying it.

    Know your boundaries. Before you begin store shopping for your upcoming auto or truck, decide what you can manage to spend, and adhere to it. Don’t forget to add curiosity about your computations. You will definitely pay around 20 % as an advance payment as well, so be prepared.

    Well before seeing a car dealership, know what sort of motor vehicle you want. Analysis each one of you options just before buying in order to evaluate which works for your budget and family members requirements. Do your homework to find out how much you need to be paying for any possible auto.

    Before signing any commitment spend some time to go through every single collection, like the small print. If you find anything at all listed that you simply do not comprehend, will not sign up until you purchase an answer which you comprehend. Unsavory salesmen may use a legal contract to put in many service fees that were not reviewed.

    In the event you maintain the preceding advice at heart next time that you simply go looking for a car, you will be prone to get a good deal. Purchasing a automobile lacks as a head ache. Simply use the tips with this report and you may get the vehicle you need at the great cost.

Leave a Reply

Your email address will not be published. Required fields are marked *