One Inch of Power: Bulk file relocation

Posted on

Hi guys,

Back for another installment of One inch of Power. In this episode, I became sick of seeing my music folder full of folders for albums, each of which may only have a single file or two.

I wrote this one incher to grab all folders with less than three files and move them all into a single folder, for ease of sorting.

"$HOME\Music" | gci | ? PSIsContainer -eq $true | % {
   if ((gci $_.FullName -recurse).Count -le 3){
      gci $_ -recurse *.mp3 | move-item -Destination $HOME\Music\misc 

Here’s the overall flow.
1. Get Items from $HOME\Music
2. Filter down to only ones where PSIsContainer equals True, which returns only folders
3. If the number of items in the folder is less than or equal to three…
4. …get a list of all files in the directory
5. Move all of those items into $Home\Music\Misc

Pretty amazing what one line of PowerShell can do.

Slide Deck, photos and resources from my Session at ATLPUG

Posted on

This slideshow requires JavaScript.

The Atlanta PowerShell User’s Group first meeting at iVision went off wonderfully! We had a solid turn out, plenty of pizza and soda, and talked a whole lot about PowerShell, what’s new, and whats coming.

Here’s the demo I worked through exploring features using the ISE.  Props to Mike Robbins for showing me this technique!

#Check our Version, needs to be greater than 5.0.  version 9814 is the most up to date version (September preview)
Get-host | Select-Object -Property Version

#region Working with Archives
Set-location C:\Demo

#Something to do with Archives, so lets look for ZIP
Get-Command *-Zip

Get-Command *-Archive

Compress-Archive -Path C:\demo -DestinationPath c:\demo\ -CompressionLevel Optimal
#mkdir Unzipped


#region Modules
#Find-module                    #xActiveDirectory, xJea, 



#region #ONEGET

#One-Get is Apt-Get come to Windows.  It is awesome!

#Import the Module
Import-Module OneGet

#List all commands for the module, will prompt to install nuget
Get-Command -Module OneGet

#Search your repo's for packages available DONT RUN!
$OriginalPackages = Find-Package

#Number of packages
Find-Package | Measure-Object | Select -Property Sum

#Not that many apps, where'd they all go?  Let's check our package Sources

#by default, we only have PSGallery and MSPSGallery as sources...let's add Chocolatey.  Previously this was Add-PackageSource, it's changed!
$PackageSourceLocation  = ""
Register-PackageSource -ProviderName PSModule -Name Chocolatey -Location $PackageSourceLocation -Trusted -VERBOSE

#After adding Chcolatey DONT RUN!
$FullPackages = find-package 

#Total count of packages now ~
Find-Package | Measure-Object | Select -Property Sum

find-package evernote 

#Search for apps with a summary that mentions PDF
find-package | Where Summary -like "*pdf*"

find-package evernote | install-package -force

#region Convert-FromString
$TraceRT = tracert -h 6 -w 45 #hops 6, -waiting 45 milliseconds

$TraceRT[(3..12)] #Skip the first few lines

$TraceRT[(3..12)] -replace "^\s+" | ConvertFrom-String -PropertyNames Hop,Latency1,Latency2,Latency3,ServerName,ServerIP #Props to Francois Xavier Cat for this regex and general idea

$TraceRT[(3..10)] -replace "^\s+" -replace 'ms','' -replace '[ \t]+$','' | ConvertFrom-String -PropertyNames Hop,Latency1,Latency2,Latency3,ServerName,ServerIP


#region DSC Stuff
#Remove-item $env:windir\system32\MonitoringSoftware -Confirm -Force

Configuration InstallXMLNotePad

    Node $MachineName
        File InstallFilesPresent
            Ensure = "Present"
            SourcePath = "\\localhost\Installer"
            DestinationPath = "C:\Demo\InstallFiles"
            Type = "Directory"
            Recurse=$true       # can only use this guy on a Directory

        Package XMLNotePad
            Ensure = "Present"  # You can also set Ensure to "Absent"
            Path  = "C:\Demo\InstallFiles\XmlNotepad.msi"
            Name = "XML Notepad 2007"
            ProductId = "FC7BACF0-1FFA-4605-B3B4-A66AB382752D"
            DependsOn= "[File]InstallFilesPresent"




Start-DscConfiguration -Path InstallXMLNotePad -Wait -Verbose -Force

#Cleanup Demo
Unregister-PackageSource -ProviderName PSModule -Name Chocolatey

Here’s the function we created on stage, which recieves and parses output from Trace Route using Convert-FromString.

function Test-Route{

      Write-Host "Tracing Route from localhost to $Servername, capturing $Hops Hops and waiting $Wait MS"
      $TraceRT = tracert -h $Hops -w $Wait $ServerName #hops 6, -waiting 45 milliseconds

      $TraceRT[(3..10)] -replace "^\s+" -replace 'ms','' -replace '[ \t]+$','' | ConvertFrom-String -PropertyNames Hop,Latency1,Latency2,Latency3,ServerName,ServerIP

Question Time : Why Won’t My Script Run?

Posted on Updated on

Accepting Scripts for Review!

I love it when people send me scripts that don’t run, or ask for help when they encounter issues.  For me, part of my own learning solidification process is trying to explain things to others.  If I can’t explain it to them, then I really don’t know the topic as well as I think I do.  If you, dead readers, ever have a script or function that just won’t run, never hesitate to send it to me.  I’ll do my best to answer your problem in an understandable and friendly way, and hopefully we’ll both be the wiser.  If you’re okay with it, I’ll post it here for others to enjoy too!

-Parameter Binding OMFG

I got an e-mail from a colleague today.  He said that this simple script kept failing:

$servers = get-content c:\temp\servers.txt
Test-connection $servers -count 1 | export-csv C:\temp\Server.csv

He sent me a copy of the file, which looked like this:


Running the command would give him (And me too!) the same output! Read the rest of this entry »

Impractical One-liner Challenge

Posted on Updated on


My thanks to Mike F. Robbins and others on reddit who pointed out that the command should be ‘Select -ExpandProperty DistinguishedName’, and not organizationalUnit.

The Challenge

A colleague and I got into a competition earlier today. How could we display an Out-Gridview of all of a companies OU’s, and then move a computer to the selected one in a single line of code.

We condensed our code down to the following two lines:

$destinationOU =  Get-ADObject -Filter 'ObjectClass -eq "organizationalUnit"' | Select -ExpandProperty DistinguishedName -Unique | Out-Gridview -passthru

Get-Content .\Computers.txt | Get-QADObject | Move-QADObject -NewParentContainer $destinationOU -whatif

The goal? Make it into a one-liner.


  • Maintain the steps if possible.  Minimally acceptable solution:
    • Get user input for which OU
    • Get a list of computers and move them to the OU
  • NO CHEATING WITH Semicolons or backticks
    Doing the below doesn’t count

    $ou = Out-Gridview;gc Computers.txt | Move-Computer $ou

Nope, sorry, try harder.

  • Anything else goes!

Please comment here with your answers. I’ll post my own within a few days.  Also, if you have any ideas for a future impractical One-Liner Challenge, let me know here, Twitter, or Reddit!

Adding Autocomplete to your Textbox forms in PowerShell

Posted on Updated on

Today I had a fun little challenge come-up: how do I go about adding Auto-completion records to my forms?

Turns out it is pretty easy! Let’s start very simply. The following will draw out a small box with an OK button, a textbox, and…thats it. Hitting OK will pass along the output of the box.

Read the rest of this entry »

Goodbye fingernails: I’m going to be speaking in ten days

Aside Posted on Updated on

You know, like in front of people.

Who will be looking at me and listening to the words I say.

What have I gotten myself into?!

[PSCustomObject] Need not apply;How PowerShell 2.0 handles objects

Posted on Updated on

Today at a client I had to export some Exchange Information from a one of their Exchange boxes. A simple task, but I kept experiencing some strange issues when I would run my script in PowerShell on the Exchange servers.

The only data I needed was RecipientType, LastLoggedOn and some other similar info, which is also easy to get. It needed to be extracted from Exchange and made ready for assimilation into a larger spreadsheet, so exporting as a Custom Object of some form would be the way to go.

I quickly came up which this script, which should have been more than up to the task. However, the output was very bizarre.

$Array = New-Object -TypeName System.Collections.ArrayList

Function Get-MarkInfo {
   ForEach ($user in $users){
      $mbx = Get-Mailbox $user
      $mbxstat = Get-MailboxStatistics $user
      $Array.Add($obj) | Out-Null
   $Array | export-csv C:\temp\EmailExport.Csv

This shouldn’t export these sorts of things

Oh no…why is my glorious [PSCustomObject] master race appearing as a hash table? No one asked for key:value pairs!

Read the rest of this entry »