replication for SYSVOL

 

A pipe is a connection between PowerShell commands. Think of it like an assembly line: start with raw materials; pick, choose and modify; then finally package and execute.
If you’re moving files around, start with the raw material, your SharePoint site. Next get the lists and document libraries in it. Then pick out only the one you want. Look at all the items in the list, filter them down to the ones in question and you’re ready to move files around. This is what we’ll cover here.
First, some details. To pipe, use the vertical bar character between commands. On a regular US English 101-key keyboard, it’s Shift-Backslash. Many cmdlets in PowerShell can consume objects from the pipe and the piped input is the default parameter.
You may have used piping before. If you ever used the Select-Object cmdlet, you probably piped into it. In fact, you probably never typed Select-Object, you just piped the output of something else into select and gave a list of fields. So if you were trying to view the number of items in each list in a web, you may have done something like this:
$web = get-spweb http://localhost
$web.lists | select title, itemcount
Or maybe you used Format-Table, abbreviated ft:
(get-spweb http://localhost).lists | ft

Those were two of the first PowerShell cmdlets I learned and I still use them more than most other cmdlets.

In the first example above, you’re piping a collection of SPList objects into the Select-Object cmdlet. Most cmdlets have an abbreviation and the Select-Object cmdlet takes a list of fields as parameters. Get-SPWeb outputs an SPWeb object (it represents a site; SPSite represents a site collection). The SPWeb object has a property called lists which outputs a collection of SPList objects. Thus, you glue one thing into another.

Format-Table is similar, it requires no parameters and normally outputs no objects to the pipeline. All it does is reformat the objects input to it for clean display on the screen.

Now that we’ve got the basics down, let’s move onto something a little more complicated and specific to the problem we’re trying to accomplish. Remember, we’re trying to read all the picture files in a document library and move certain ones to a folder. Let’s try this:

“http://localhost“ |
get-spweb |

foreach-object { $_.lists } |

where-object { $_.name –eq “Company Pictures” } |

foreach-object { $_.items } |

where-object { $_.name –like “* *” }

For starters, we’re doing this in multiple lines. You can type them into the PowerShell window like that, the interpreter knows that since you’re ending each line on a pipe, there’s got to be more coming. It’ll prompt you for the next line.

Next, you’ll see that we’re starting with the URL. It’s just a string object and it’s a single item. Get-SPWeb accepts URL strings from the pipeline, so we’re starting with the string and piping it to Get-SPWeb.

Then, we’ve got two new cmdlets, ForEach-Object and Where-Object. If you’ve ever done any programming or shell scripting before, these are probably familiar. ForEach-Object does something for each object it’s passed. Where-Object filters out items where a condition is true.

There’s also a new construct in there, the brackets with the special variable, $_. The brackets allow you to execute multiple commands, like a function. If you had more than one command in the brackets, you could separate them with semicolons. The special variable $_ tells the system to use the input argument to the bracketed function. ForEach and Where do things once per item in a collection, so the $_ is the current item.

Finally, we’re doing some comparisons. PowerShell uses comparison operators like some Unix shell systems. –eq means equals, -lt means less than, etc. We’re also using –like, which does an approximate string comparison. In the last line of our example, notice there’s a space between the two asterisks. That means that we’re looking for anything with a space in it, with anything (or nothing) before and anything (or nothing) after.

In just a few lines of PowerShell, or really only one if you decide not to break it up, we’ve filtered down to just the objects we want. See how easy that was?

But why? Why bother with this piping stuff? It gives you a lot of options for:

  • working with groups of objects,
  • re-using scripts, and
  • saving things for later.

We’ve already seen how we can work with groups of objects. As an administrator or developer, you’ll probably understand how important and useful this is. Using the SharePoint Central Administration UI, you can only do things either one at a time, or using the multi-select checkboxes. This is good for small numbers of items but much more bulky and difficult for hundreds or thousands of items at a time.

After these examples, you can probably see how this makes reusability easy, as long as you know one thing: you can create a script to stop anywhere in that chain of pipes. If you were often doing things with the list items in the Company Pictures document library, you could put everything up to the last line in a script file, then re-run it and pipe it into something else later.

More importantly, consider the value of your data. If you moved these files around using Central Administration, you’d go straight to the production server and make your changes. If you were tired that day and made some mistakes, things would end up in the wrong place. Testing that process in a test environment wouldn’t help much either: the mistakes you make in staging could be totally different than the ones you make in production. But if you script this, you can try it out in staging then run exactly the same thing in production after you’ve verified it’s perfect. Use a copy of your production data in staging if you need to and take all the time you need to verify the results, knowing that once you’ve scripted it correctly, it will do exactly the same thing in another environment.

We’ll talk even more about the reasons for using PowerShell in upcoming blog posts.