Cryptic PowerShell One-Liner to Clarified Script, Part 1

Cryptic PowerShell One-Liner to Clarified Script, Part 1

Break long one-liners into a series of shorter lines

Last month, in “From PowerShell One-Liner to Script,” we stuffed a long-winded (but useful) one-liner into a text file, saved it (with a filename such as C:\scripts\fdns.ps1, where fdns is short for Fix DisplayNames and PowerShell scripts require the extension .ps1), and thereby created a simple PowerShell script:

get-aduser -filter * -properties * | foreach { set-aduser $_ –displayname ($_.givenname + " " + $}

In that article, I explained that although you end up with a script that’s about as opaque as the original one-liner, it’s easier to invoke because typing the script’s name (C:\scripts\fdns) is much easier than re-typing that monster above. Unfortunately, the justification “it requires less typing” is fairly weak for inserting a one-liner into a text file with the extension .ps1, so let’s examine another reason or two. 

One stronger justification is that scripts let you break ugly, long one-liners into a series of shorter lines that are more easily understood. Easier-to-understand scripts are then more inviting to extend and expand, increasing the chances that you’ll take the time to give the script extra capabilities. For example, you might want to give this script the option to only do its DisplayName cleanup on a given organizational unit (OU) rather than an entire domain. Alternatively, perhaps you’d like to add the option for the script to report all of the new DisplayName values. You might even want to act like a big-time programmer and add comments—chunks of readable English that explain what the script is trying to do and how it’s trying to do it. No matter why you want to script-ize a one-liner, your first priority is breaking it up into multiple lines. 

The first way to break up a one-liner is to separate it into two lines: on the left side of the pipeline, a line that gathers certain items, and on the right side of the pipeline, a line that performs a task on those items. Recall that most one-liners look like

(Use get-something to retrieve some objects/accounts) | (do something to/with them)

Such a one-liner can be broken up into two lines, like this:

$somevariablename = [the command to retrieve some objects]
$somevariablename | [the command(s) to do something with the objects]

In the case of our one-liner, the “retrieve” sequence is get-aduser -filter * -properties *, and the “do something” part is everything from foreach to the end. To use this formula, just pick a variable name—any will do, but a descriptive one is best, such as $allusers) and you’ll end up with these two lines:

$allusers= ( get-aduser -filter * -properties *)
$allusers| foreach { set-aduser $_ -displayname ($_.givenname + " " + $}

Type those two lines into another text file, give it a name such as C:\scripts\test2.ps1, create a test AD environment, and in that environment type C:\scripts\test2. You’ll then get a new set of DisplayNames.

How does that work? Recall that variable names must start with a $ symbol, and those simply represent areas in your computer’s RAM that temporarily stores things. Get-aduser, the first command, just gets user objects, and the first line stores a copy of all of the domain’s user objects in it. (Try typing $allusers and pressing Enter, and you’ll see information about all of your users dumped onto the screen. The second line starts with $allusers |, and that has the effect not of dumping all the users onto the screen but instead stuffing them into the pipeline, where they can be received by the right-side part of the one-liner. The variable merely facilitates the two-line breakup.

So now you’ve made a two-line script. How is that better? For one thing, you can insert comments. A comment is any text following an octothorpe (#)—PowerShell ignores any text to the right of #. You could then dress up the script with a few comments, like this:

#DisplayName Fixer
#Takes all domain users' given names and surnames, glues them together with a blank
#between them and overwrites the current DisplayName with the first/last name
#This MODIFIES YOUR AD. Don't run it unless you know what you're doing!
#First, collect all AD user accounts into a temporary variable "UsersFound:"
$UsersFound = ( get-aduser -filter * -properties *)
#Now that you have them, feed the users to a set-aduser command:
$UsersFound | foreach { set-aduser $_ -displayname ($_.givenname + " " + $}

It’s reasonable to assert that what you’ve done here (separate “get objects” from “modify objects” into two lines and add high-level explanatory comments) makes this script clearer than the one-liner.  But you can do more by taking that right-of-the-pipeline sequence and spreading it out into more lines. We’ll do that next month!

Hide comments


  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.