@Dread First You asked how someone would get started with Windows scripting as someone who has very basic Bash knowledge. I'm replying here and tagging you because I don't want to clutter the Linux thread with Powershell talk (again). You've already had one reply but there were a couple of things I felt could throw you off in that. In particular, there was a suggestion that you should just grab cmd.exe and also a suggestion that you might want to begin by using Powershell on Linux.
The best environments for scripting on Windows are either the Windows Terminal or VS Code. To grab the former, either just type "Windows Terminal" into the MS Store or go
here . It's a nice, tabbed environment for Windows operations. Alternately open (or install) VS Code and that has a terminal built in (short cut is
Ctrl + '). The nice thing with VS Code is that you have an editor write there for writing out actual Powershell scripts, with syntax highlighting ready and you can just run the script from there by clicking the run icon. The standard extension for Powershell scripts is
.ps1. I suggest you start off with some command straight in the terminal and then progress to writing actual scripts once you've had some fun there.
Although you can get Powershell for Linux the reason I suggest you don't begin with this, even if you are more familiar with a Linux environment, is because both Bash and Powershell are designed for their environments. Well, Bash is more evolved than designed but the point stands. Specifically what I'm referring to is that the entire Windows OS is exposed as Objects. It's Object Orientated from start to finish and Powershell works with objects. Very nicely, too. Bash cannot pipeline objects. That means it cannot directly take an object from one command and "pipe" it to another command. It can only pipe text. That's okay in a Linux environment where it's not dealing with objects much anyway and all its standard tools just spit out text. But it's a crappy fit for Windows (and not great on Linux, imo). Conversely, whilst Powershell will work on Linux you're not really getting to understand the power of it or the typical toolsets when on Linux.
So, you've got either Windows Terminal or VS Code (and opened the shell in it as described above) and you want to try some Powerhshell. Where do you start? Well, there are quite a few commands that you'll already be familiar with because they were imported from Bash to help people transition. (Not like that - you're not a Rust developer). So you can type
ls,
cd,
mv and a handful of others. But they're not actually the same GNU programs and you may notice that the outputs can be different. For example, on Linux to get all the extended file information like timestamps and ownership, you'd type
ls -l. But on Windows just ls will get you that by default. Why? Well it's a bit more interesting than simply having different defaults. The reason is that on Linux,
ls is a program that returns a pile of text data whilst on Windows, it's actually returning an array of file objects. This is more significant than it sounds (and more useful!). By default, when the shell gets an array of objects back it's just going to turn them into text
for you. But you don't have to let the shell get that output. You could type
ls | Format-List . Try it in a directory. You'll see it does something much more interesting. Try
ls | ConvertTo-Json or
ls | ConvertTo-Html. You couldn't do this in Bash because whilst you can pipe the output of ls to another command, it's only text and no matter what the receiving command, it can only work with what is there. So if it wants to add something additional it has to go back to the file system and request the file itself and check it. It's more complex.
That's probably a bit of an esoteric place to start when you might have been expecting a few Powershell commands but I think it's a good thing because it clues you in right from the start of a fundamental difference between what you're used to and what you can do on Windows with Powerhshell. If you understand that each step in Powershell is returning an object and that you can pipe an object to the next command and the output of that to the next and so on, very soon it becomes natural to throw something like this together:
Get-ChildItem -Recurse *.* | Where-Object { (Select-String 'myString' $_) } | Select-Object -Property FullName
What's all that doing? Well you should have a go and try and figure it out for yourself, first. You'll get surprisingly far, is my bet.
Get-ChildItem is probably the least intuitive but it does exactly what it says. It gets child items of the current object. Which by default, your current working directory. If the name seems a little odd it's because it works with more than just directories. You could use this with the Windows Registry, which is also hiearchical, just like a file system.
So try out Get-ChildItem by itself in a directory, you get everything in it. Throw in -Recurse flag and you'll get everything recursively all the way down. Throw in a pattern to match on the end like *.txt and you'll find all files that end with .txt. Play with that. Great. Each time you run that you're getting an array of file objects back. Now you can "pipe" them onto another command. Here I used Where-Object. That's a filter cmdlet (little program designed to work in Powershell) that evaluates a criteria on each object passed to it. In this case, the criteria is whether the file contains the string 'myString'. $_ is the standard placeholder for a passed in object.
The main thing with this example is that it's not immediately obvious but very quickly you'll find you understand it, and that's nice to demonstrate you're learning.
What's the Linux equivalent of this? Well it's
grep -rl myString * . Wow - see how much shorter the Linux version is. Great right? Well.... it's actually less intuitive. If you know what the r and l flags are, it's quicker to type. But you can't do it intuitively the way you can with
-Recurse. And what the fuck is
-l and why do you need it? Well you need it because you want the output format to be just the file names because grep contains its own output formatting code. And so for some things you might want to pass this output on you'll need it. For others you wont. That's not very flexible. The command needs to have knowledge of how its output will be used at the time it runs. That's backwards. Get-ChildItem is returning an array of file objects. Every time. It doesn't care whether the recipient is going to do operations on those files, format them as JSON or just dump them to the shell for display. That's a lot cleaner.
A bunch of what I'm saying will seem not that important right now but if you get into serious scripting these fundamental differences make all the difference in the world. Powershell gets very powerful very quickly. Anything you can do in the GUI you can do in Powershell and a lot more. For example, I had directories full of gifs that I wanted to convert to webms. I wanted the original gifs to be placed in a new folder once the webm was completed. I wanted it to run multiple operations in parallel up to a set amount and I wanted it to report back its progress to me. I had a nice parallelised Powershell script which was spawning new processes each time the number of concurrent processes fell below my specified number, and each process called the Handbrake CLI executable that was doing the conversion. The whole thing was very neat, if I do say so myself. And worked great for something I didn't have a convenient way of doing otherwise.
I'm out of time right now but I hope that was interesting. I'd start with just having a play around with some basic file operations - searching directories for files containing certain strings, filtering out certain types of files. And then once done, start writing some basic Powershell scripts with loops and conditionals. You'll need to change a security setting on your Windows install probably.
Oh, and this goes without saying - don't do something stupid from the wrong place and delete all your files!