Hello everyone! In this video series I’m going to be covering
how to use PowerShell, right from the absolute basics to near mastery. PowerShell is extremely useful, but a lot
of people don’t quite get how it all works, and they don’t know what they’re really
doing, so they miss out on it a lot. However, this series will cover everything
you need to know to really start doing things with PowerShell! Now, just before we get into it, I do want
to point out that this series assumes you know a bit about command lines. So, you know that you press ENTER to run a
command, and you know what “cd” and “ls” is and all of that sort of stuff, I assume
you know the basics there. I’d also just like to point out that if
you are a C# programmer, like I am, then you may not really need all of this series. PowerShell should be very easy for you because
PowerShell is built on top of .NET, which is the same thing C# is built on. This series assumes you know nothing about
the C# programming language and .NET, and don’t worry because I’ll explain how it
all works nice and simple. Alright! Enough introduction! Let’s start looking at PowerShell. The first thing we need to do is actually
get it setup, we can’t exactly do anything before that. Now, Windows comes with PowerShell, as you’ll
see if you search “Windows PowerShell”. However, I don’t want you to use this, because
this is an old version of PowerShell, version 5, and they aren’t planning on updating
it anytime soon. What you actually want is the “proper”
new PowerShell. If you go onto the GitHub page here, linked
below, you’ll find download links for all different platforms, Windows, Linux, all of
it. I’ll leave you to install it for yourself. Alright, finally, let’s dig in! The place to start is the very simple concept
that PowerShell is built upon, and this will be our building block for everyone to come. In other command line interfaces, like let’s
say bash. Every command you use gives you back one thing. That one thing is text. That’s all you get. When you do “ls” for example, it outputs
text and hands it over to you. And you can pipe the text to another command,
and that’s it. Sure, it’s simple, but also extremely limiting. For example, what if I wanted to get all the
txt files and run some command on them? Well, turns out that to do that you don’t
use ls at all, and you use some weird syntax that only works for files to do it. And sometimes there isn’t some fancy syntax
you can use, and you have to try and read through the text the command gave you, and
you have to try and extract out the thing you want- Oh, it’s just horrific. However, PowerShell takes a different approach. Commands don’t give back text. They give back “objects”. And each of these “objects” represents
something. For example, let’s look at “ls”, which
does exist in PowerShell too. Unlike in bash where it just throws text at
you, PowerShell gives us a load of objects, and each of those objects represent a certain
file and folder. Let’s look at one of these objects a little
closer. Every object is made up of smaller parts,
and to keep it simple we’ll refer to these as properties. For example, if we have an object that represents
a file, it will have a “Name” property, which is just the name of the file. Maybe some kind of “Path” property too,
which represents the whole path to the file. Maybe an “Extension” property too, and
lots of other file-related properties, like permissions and such. There’s a lot more to these objects as we’ll
learn soon, but for now, let’s keep it at this. Now, let’s go into PowerShell and run “ls”
ourselves and see what happens. So, we type “ls” and you’ll notice that… This looks similar to what we get in bash. And I know you might be thinking now: “Wait
a minute, commands don’t give text, so why are we seeing text here?”. And the reason is because this text we’re
seeing here isn’t actually coming from “ls”. What PowerShell is doing is it’s showing
us the objects in a nice, text form. PowerShell has looked at the objects “ls”
gave us, and it made it into a table so we can see them all nicely, what we’re seeing
here is just here for us. So, it might look like “ls” gave back
text, but actually it did give objects and PowerShell is just showing us those objects
in a nice text view. OK, fine, we get objects out of the commands. But this is completely useless if we can’t
actually do anything with those objects. What we need to be able to do is take the
objects that “ls” gives us and give them to another command so we can work with them. And similar to bash, we use a pipe to do that. Now, what we’re going to do is use a command
called “Format-List”, written like this. What this command does is it takes in a bunch
of objects, and lists them and their properties all out, one-after-another. So, let’s do that. We’re going to run “ls”, and take all
those objects it gives us, and hand them over to “Format-List”. Then Format-List is going to turn all those
objects into a nice text-representation for us, so we can see them. And here it is. Now you’ll notice that it has listed out
each object, and each property on those objects too. There’s also a command called “Format-Table”,
which is what PowerShell actually ran automatically earlier. This shows us the objects in a table-view
like we saw before. PowerShell will work out whether it’s best
to show us a table-view or list-view automatically. Let’s look at another command, this command
is called “Get-Process”. This gives us all of the processes running
on the computer. And I know that “Process” isn’t plural
there, it’s weird, but PowerShell likes to name commands like this. For example, getting all the services on a
Windows machine is “Get-Service”. Not plural. And so on. Anyway, if we run “Get-Process” it will
show us all the processes we have running on our system, and here they all are. Again, PowerShell chose a table to show us
what the objects are. Let’s look at these tables a little closer. So, along the top here you have the names
of what PowerShell considers to be the most important properties, like the “Name”
and “Id” and such. And then each row is a certain object and
what those properties are in that object. If we use “Format-List” it will show these
objects in a list instead. Each section represents an object, and it
tells us what each property is for each one. So, they’re just different ways of seeing
the objects. Another neat little command is “Measure”
(short for “Measure-Object”). This tells us how many objects we got. So, we’ll take all the objects “ls”
gives us and we’ll put them into “Measure”. And we see if we look at the “Count” here,
it tells us how many objects we got. Now, you’ll notice that measure can also
get the average and sum. Now in this case, we didn’t ask for it,
so it didn’t even try, and if we did it wouldn’t work in this particular case anyway
because you obviously can’t exactly work out the average of entire folders. But if we gave it a bunch of number objects,
we could work out the statistics of them with “Measure”. Also, notice how for once PowerShell actually
chose a list view! It probably did this because “Measure”
only gave us one object, and that object just had five little properties in it. But if we really wanted it to show it as a
table, we could take this little object here and give that to “Format-Table” … I
think you can see why it preferred a list view here. Now, I know this line looks pretty long, but
let’s just break it right down so we know exactly what’s going on. So first we run “ls”, and this gives us
a load of objects. Then, what we do is we pipe over those objects
into “Measure”. What “Measure” does is it analyses the
objects and works out the count and sum and things like that. And it gives us another object with those
values in it. And then finally, we give that small little
object there to “Format-Table”, which turns it into text and PowerShell prints that
out for us. It’s all one nice chain, one after another. So, so far, we’ve got a pretty good idea
of how this system works. But let’s look at some important commands
you’ll actually be using a lot with PowerShell, instead of just going through random commands
to demonstrate. The first command is called “Where”, and
this is an extremely important command. What “Where” let’s us do is it lets
us “filter objects down based on a certain condition”. OK, let me explain what that actually means. Let’s think about our example from earlier
about getting just the read-only files. What we would do in PowerShell, is first we
would run “ls” to get all the files, and then, we would give each of those files to
“Where”, and we would tell “Where” to give us just the objects that have the
“read-only” property set. That’s what it does, it lets us limit a
bunch of objects down to just the objects that match a certain condition. Another example, and the one we’re going
to write, is getting all the files with the “txt” extension. First, we would run “ls”, but then we
would give those files to “Where” and we would tell it: “Give me only the files
that have the ‘txt’ extension.” So, let’s look at how we use “Where”. Now it looks a little weird at first, but
I’ll explain what this all means later, it’s just how to use it that matters at
the moment. What you do is you write “Where” and then
follow it by these curly braces here, and inside these curly braces we put in our “condition”. The condition is what we want each item to
have. So, in our first example, the condition would
be “where the file is read-only”, or in our second example it would be “where the
file has a ‘txt’ extension”. Let’s write out the second example now. To write the condition we first write this,
and it will look a little funny at the start, but you’ll get used to it, and you’ll
learn what’s really going on here in a future video. We write a dollar sign, followed by an “underscore”,
and a “dot”. Again, it looks weird, but it will make perfect
sense when we learn about variables later. Then, after that dot there, we write what
property we want to look at. Now, in our case, we want to look at the Extension
property. Remember, we want to get all the items with
a “txt” extension, so we need to be checking the extension, don’t we? And then, next we want to say equal to. Now PowerShell does this very weirdly, but
we say equal to by writing “-eq”. So, so far, we have “Where the item’s
extension equals”, and now we want to say what we’re expecting it to equal. We’re expecting it to equal “.txt”,
so we’ll write that. Now, because the extension is text, it’s
very important that we put the “.txt” into quotes. We’ll learn about text and numbers and all
of that more in-depth later, but just know that if you want to represent text in some
way, you should put it in quotes. You can use single quotes or double quotes,
both will work, but I’ll be using single quotes here. And now, let’s run it! And look, we only get the items that have
an “Extension” of “.txt”. And what I personally really love about this,
is this “Where” will work on everything. It’s not just “ls”, it will work on
“Get-Process”, “Get-Service”, “Get-Command” and all of them. Just pick a valid property and we can filter
down by that. If I instead wanted to limit it based on the
name, I could just write “Name” here and what I want to compare it to, and now it’s
only the ones where the name equals that, which is obviously just going to be this one
object here. However, we can take this further. This “-eq” here means “equal to”,
so it checks whether it exactly equals to something, but there are other things we can
use here too. For example, if we use processes instead,
we can look at their CPU time and say where the CPU time is greater than 5. In fact, let’s do that. We’re going to ask PowerShell for all of
the processes with more than 5 seconds of CPU time. In PowerShell to do “greater than” we
write “-gt”. So, let’s do this! The first step is to get all the processes. And then, we’ll use “Where” here to
say that “only if the CPU is greater than 20”. Now since this is an actual number, and not
text, we won’t write quotes. Again, I’ll cover these things properly
later. And look at that! It gives us all the processes that have a
CPU greater than 20. And we could add a “Measure” to the end
now. Now it tells us how many processes have a
CPU greater than 20. To break it down. Get-Process gives us a bunch of process objects,
then “Where” gets rid of all the ones that don’t have a high CPU and then “Measure”
counts how many of those there are. Pretty simple, right? Let’s drop the “Measure” and use a different
command. Now this is all nice here, but they aren’t
ordered, and I want to them to be ordered by their Id. To do this, we can use a command called “Sort”. And the way it works is quite simple, we write
“Sort”, and then inside curly braces we tell it which property we want to sort it
by. So, in our case, we want to sort it by the
Id. And that’s literally all it takes, look,
they’re sorted now! So, if we look at our command here, while
this may look a little odd in places, it’s very clear and understandable. Let’s just quickly compare this to what
the equivalent for Bash would be and- Oh… Oh god… Uh, let’s just… Put that away, and focus on the PowerShell. OK, so, what exactly does all of this weird
“$_” stuff mean? Let’s just look at an example “Where”
command here. Now a lot of the condition is quite self-explanatory,
we’ve this weird bit here that I’m about to explain, but then we say which property
to compare, how to compare it (so, in this case whether it’s greater than), and what
we want to compare it to. I’d say that’s fairly simple. But what does the weird bit mean. Well, it’s actually made up of two parts. There’s the “$_” which is one part,
and then the “.”, which is another. The “Where” runs this condition on every
single item. So, if we run “ls” and it gives us 3 objects. “Where” will run our condition three times
and each time it will replace this “$_” here with our object and see what the condition
says. So, all the “$_” means is which item we’re
currently comparing. And it gets swapped out for each item. And then the dot tells PowerShell that we
want to access one of the deeper properties on the object. That’s… it. It looks a lot more complicated than it really
is. Alright! We’re coming towards the end now, at this
point you already have a very strong footing in PowerShell. So far, we’ve learnt three out of the four
must have “organisation commands”. First, we learnt “Measure”, a simple command
that tells us basic statistics about objects. It tells us their count, their average, their
sum, and so on. Then, we learnt about “Where”. This one is extremely important for filtering
down objects to just the ones you’re interested in. Then, we learnt about “Sort”, which orders
all of the objects depending on one of their properties. But there’s still one more must-have command
that you need to know. And at first, it’s actually the hardest
one to understand. But once you get it, it’s very powerful. This command is called “ForEach”. Now, the reason it’s the hardest to learn
is it’s used for two slightly different things. It does one thing, but it gets used in two
ways. What “ForEach” does is it goes through
each object you give it, and it does what you tell it to for each one. For example, if we run “ls” again, in
this folder here, we get three files. So that’s three objects, one for each file,
right? What if we want to say “I found a file”
for every one of these objects? Well, we can use “ForEach” to do that. So, to do this, first we’ll get all the
files, and then we’re going to give these to “ForEach”. To use “ForEach”, we write “ForEach”
and follow it by curly braces, and whatever we put inside these curly braces is what will
happen for each object. To print a message, we can use “echo”,
just like in other command lines. And we want to print “I found a file”
for each one of those objects. So, let’s just clarify what’s happening
here. We run “ls” which gives us a bunch of
objects, and then we give those objects to “ForEach”, and “ForEach” will run
this code here for each of the objects. Which means that it will write the message
out three times. And that’s what it does. It does some action on each one of the objects. However, that’s not quite all there is to
“ForEach”, there’s just one more part. You see, “ForEach” doesn’t have to be
at the end of the chain, because it actually gives back some objects as well. It gives back a bunch of objects, and each
one of those objects, is the result from running the code inside the curly braces. So, if I had 3 files, and I did something
like this, what I would get is three objects that are each just the number “3”. Because it’s gone through each item and
saved the result from each go. And we can then pass these objects on again. Now, you might think this isn’t very useful… However, this brings us onto the second way
“ForEach” is used. We can use “ForEach” to filter objects
down to just one property. Let me show you how. If we run “ls” here are our trusty three
objects. Each one of those objects has all of these
(and more) properties on them. Now, that’s fine, and there’s no problems
with that… But let’s say we now decide that we want
to work out the average of their sizes. Well, to do that, we would use “Measure”
… But “Measure” would try to work out the average of the entire objects, and, as
we know… It fails. What we want to do is get just the sizes,
nothing else, just the “size” properties on their own, and then hand those to “Measure”
to get processed. Well, we can do that with “ForEach”. Now, let’s work with something that’s
actually on the table view here, how about the name? But this obviously applies to other properties. What we want is just this property, just this
column right here, and none of things surrounding it. All we have to do is we get the “ForEach”
to access this property each time it runs. And to do that, as you’ll remember from
earlier, we can use “$_”. This will let us access the item we’re currently
on inside the ForEach. So, literally all we have to write in here,
is just “$_.Name”. Let’s see what exactly is going on here. We run “ls” and we get all of our files. Then, we tell “ForEach”: “Right, for
each of the items get the ‘Name’ property”. So, “ForEach” starts processing the first
object. It substitutes “$_” for the first object,
and we tell it to get the “Name” property on it. And, as I said earlier, “ForEach” will
save the result of what’s in the curly braces, because that’s what it does. Then, it moves onto the next object. It substitutes “$_” for this object, and
we get its name. And then it saves that name. And then we repeat that again and again for
all the objects. And you’ll notice that what we end up with
is all of the names, on their own. Hopefully, this diagram really helps visualize
what’s going on. Alright, we’re coming to the end, there’s
just one quick thing I want to mention that you’ll need in a moment. “Measure” won’t actually try to calculate
any of the other things it shows unless you specifically ask it to. So even if I give “Measure” a bunch of
numbers, the average will still show up as blank. You need to tell “Measure” that you actually
want it to calculate the average, and you do that by writing “Measure -Average”,
so just keep that in mind. Alright, let’s apply everything we’ve
learnt now! We’re going to get all of the processes
with an ID above 4000 and work out their average CPU time. And I want you to try and do this on your
own. Pause the video now to give it a try. If you’re stuck, it comes down to these
steps. First, get all of the processes. Next, filter it down to only objects with
an ID above 4000. Then, filter it down to just the CPU time
on its own, so nothing else gets in the way. And finally, use “Measure -Average” to
work out the average. Alright! Let’s write it. The first step is to get all of the processes. Done. Now, let’s just run this for a moment, because
I want to look at the top of this table, so I know exactly what properties I’m going
to be working with. Later we’ll cover better ways of discovering
properties and commands, but for now the table gives us enough information. OK so, the property that contains the “ID”
is called “ID”, and the property that contains the CPU time is called “CPU”
(ignore the “s” in brackets). Cool, that will help us write the rest. Alright, then the next step is to get just
the processes with an ID above 4000. To do this, we’ll use “Where”. So, where the object’s ID is greater than
4000. Again, I want to remind you that this is a
number, not text, so we do not write quotes here. It may work with quotes because PowerShell
is a little more relaxed about this than it should be, but it’s technically incorrect,
so please keep in mind: Quotes for text, no quotes for numbers. Next, we need to filter it down to just the
CPU time, so nothing else gets in the way. We’ll use “ForEach” to do that. And on every item we want to get just the
“CPU”, that’s all we want out of each one. And, finally, we can use “Measure” to
work out the statistics. And there you go, there is our average! We can even work out the “Sum” too. So, to finish off the video, let’s quickly
summarise what’s going on here. First, we run “Get-Process” to get all
of the processes, each as an object. Then, we run hand it to “Where”, which
throws away the objects that aren’t above the ID of 4000. Then, we give it to “ForEach” which goes
through each one and extracts out just the property we’re interested in. And finally, we give it to “Measure”,
which takes those raw numbers, and works out the average and sum. And technically how many there are too. And that’s it! By this point you already know PowerShell
pretty well, but there’s still more to go. In the next video, we’re going to take a
deeper dive into commands themselves. How they’re named, how parameters work,
how to discover new commands, their aliases, all of that. By the end of this series I can promise you
that you will be an expert in PowerShell and how it all works. But until then, bye!