How To Tail With PowerShell
Tags: powershell, bash, productivity
Published: 2020-09-30 13:20:11

Printing the last or first, few lines of a file is a common operation in day to day operations.
On Linux most people will, without thinking twice, use `tail` and it's counterpart `head` to achieve this.

It's man page[^1] describes tail simply like this

> Print the last 10 lines of each FILE to standard output.
> With more than one FILE, precede each with a header giving the file name.

[^1]: http://manpages.ubuntu.com/manpages/focal/en/man1/tail.1.html

Lets take a look at some common tail operations and how to reproduce them with PowerShell.

## tail -f

```bash
tail -f /var/log/important.log
```

This is my personal top use case for tail. The `-f` switch instructs tail to follow the given file,
outputting data as it is written to the file.

With PowerShell we will use `Get-Content` and instruct it to follow the file with the `-Wait` switch.

```powershell
Get-Content "c:\important.log" -Wait
```

{% details Important! %}
There is one important difference to `tail`.
If the file being followed gets deleted the process will return with a non-zero code.
{% enddetails %}

Terminating is the same with both `tail` and `Get-Content`, just press `Ctrl+C`

## tail -n

The `-n` parameter instructs tail to return the last X lines from the given file.

Let's say you want the last 20 lines from your important log file

```bash
tail -n 20 /var/log/important.log
```

PowerShell can replicate this behavior with the `-Tail` parameter.

```powershell
Get-Content "c:\important.log" -Tail 20
```

## head -n

Head works the same way, but takes the first X lines from the given file.

```bash
head -n 20 /var/log/important.log
```

PowerShell can replicate this behavior with the `-Head` parameter.

```powershell
Get-Content "c:\important.log" -Head 20
```

## Multiple Files

Coming back to our `tail -f` example you may want to operate on multiple files at once.

With tail you can simply append them to the end of the command like this.

```bash
tail -f /var/log/important.log /var/log/another.log
```

Not surprisingly `Get-Content` works in a similar way.

```powershell
Get-Content "c:\important.log","c:\another.log" -Wait
```

{% details Important! %}

- Unlike `tail` the different files need to be comma-separated
- PowerShell will not indicate what file a outputted line belongs to

{% enddetails %}

## Shortcuts

Writing out `Get-Content` every time may seem a bit long winded or cumbersome, thankfully you don't have to.

With some shortcuts you can significantly lower keystrokes:

- Shorten `Get-Content` by using it's alias `gc`
- Omit `""` around your paths as long as they have no spaces inside
- Commands are always case insensitive, this is more of a personal preference

With this shortcuts our commands are way shorter.

```powershell
Get-Content "c:\important.log" -Wait
gc c:\important.log -Wait

Get-Content "c:\important.log" -Tail 20
gc c:\important.log -Tail 20

Get-Content "c:\important.log" -Head 20
gc c:\important.log -Head 20

Get-Content "c:\important.log","c:\another.log" -Wait
gc c:\important.log,c:\another.log -Wait

```

## Taking It Further

This covers examples for basic tail usage to get you started in PowerShell.

Additionally you can use a wide variety of [wildcards](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_wildcards?view=powershell-7) inside the path to filter for multiple files to tail.

```powershell
Get-Content "c:\logs\*" -Wait
```

Advancing from there you may want to exclude some irrelevant IIS logs and a few old log files from 2019.

```powershell
Get-Content "c:\logs\*" -Exclude "iis-*.log","*2019*" -Wait
```

A great ressource to dive in even deeper is the [official documentation](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-content?view=powershell-7) from microsoft.

Feel free to ask me about your PowerShell problem over on Twitter!