Don't you hate it when the JSON document copied from the terminal doesn't work because of extra newlines? Or getting a syntax error because the string you pasted into the terminal needs to be escaped?
Before getting a Windows laptop a while ago I primarily used macOS for over a decade. From macOS, I'm used to having the convenient pbcopy
and pbpaste
command-line tools for copying and pasting in the terminal. Not only do they sidestep these problems, but they also make it a breeze to use almost any command-line tool together with the clipboard.
So understandably, I felt bummed out when I started using WSL to run a Linux shell inside Windows and realized it doesn't come with similar clipboard tools. Luckily, we can easily add our own pbcopy
and pbpaste
commands to WSL with a couple of one-liner command-line aliases.
Getting Started
We're going to define two aliases in our WSL Linux shell. pbcopy
sets the clipboard contents from its input, and pbpaste
outputs it. Creating aliases in the shell is done with the alias
command:
alias pbcopy='powershell.exe -Command "Set-Clipboard -Value \$input"'
alias pbpaste='powershell.exe -Command "Get-Clipboard"'
The aliases can be used immediately, but will only last until the end of the session. To make sure they'll always be available, we need to add them to our shell configuration file. The configuration file lives in the home directory (~
), but the filename depends on the shell. For Bash this file is called .bashrc
, and for ZSH it is .zshrc
. The changes will only take effect after starting a new shell.
Let's put the aliases to the test with some commands. First, we'll get a random UUID by copying the output of uuidgen
with pbcopy
:
uuidgen | pbcopy
Then, let's use a copied JSON document as the body of an HTTP POST request by piping the output of pbpaste
to curl
:
pbpaste | curl -H "Content-Type: application/json" -d @- https://httpbin.org/post
By simply defining two short command-line aliases we can now use the clipboard with almost any Linux tool. In the next section, we'll explore some more interesting usages.
Using the Aliases
Most often we'll use the aliases when piping to and from other commands. A pipe is created by separating two commands with a pipe symbol (|
). The pipe passes output from the first command to the input of the next.
Piping the output from a command to pbcopy
copies it to the clipboard. For instance, to get the current UNIX time, create a pipe from date
to pbcopy
:
date +%s | pbcopy
On the other hand, piping the output of pbpaste
to another command will use the clipboard contents as its input. A Gist can easily be created from the clipboard contents by piping from pbpaste
to the awesome gh
GitHub CLI tool:
pbpaste | gh gist create -d "Gist created with pbpaste" -f "gist-filename.txt" -
In addition to pipes, redirects make copying and pasting files effortless. By appending >
and a file path to a command, its output is redirected to that file. This way, redirecting the output of pbpaste
creates a file from the clipboard:
pbpaste > index.js
Be aware output redirects overwrite existing files. To append the output to the end of a file, use >>
instead. This can for instance be used to add lines to the Bash configuration file:
pbpaste >> ~/.bashrc
Lastly, the contents of a file can be redirected to the input of a command with <
. This lets you copy entire files with pbcopy
, for instance, your public SSH key:
pbcopy < ~/.ssh/id_rsa.pub
Avoiding Pitfalls of Copy and Paste
In the previous sections, we've seen how the aliases make using the clipboard in the terminal more streamlined and enjoyable. But there are still even more benefits. The aliases solve many pitfalls of manual copy and paste in the terminal.
When using the aliases you don't have to:
- remove extra newlines when copying multiple lines
- add quotes and escape characters when pasting
- worry about copying too many or too few characters
- worry about secrets being visible
Implementing the Aliases
Before wrapping up, let's take a look at how the clipboard aliases are implemented. You might have heard WSL lets you run .exe
files inside Linux. This means we should be able to access the clipboard from WSL by using Windows command-line clipboard tools.
Conveniently, the PowerShell shell – which comes pre-installed with Windows – has just what we're looking for. Open Windows PowerShell or Windows Terminal to try out the following PowerShell commands:
Write-Output "Hello PowerShell!" | Set-Clipboard
Get-Clipboard
As you can see, Set-Clipboard
and Get-Clipboard
give us the functionality we need for implementing pbcopy
and pbpaste
. However, we still need to find a way to run these commands inside WSL. Starting PowerShell inside WSL is as simple as typing powershell.exe
. This will start an interactive shell though, which isn't what we want. Instead, we need a way to immediately run the commands and then exit. The -Command
flag lets us do just that. Armed with this knowledge we can run Get-Clipboard
again, but this time from Linux:
powershell.exe -Command "Get-Clipboard"
Now that pasting works, let's take a moment to look at copying. This time we have to pipe data to powershell.exe
, which is a bit more involved. For this we can use the $input
variable which is automatically created for us in PowerShell. Passing it to the -Value
parameter of Set-Clipboard
will set the clipboard from the data piped into PowerShell:
echo 'Hello WSL!' | powershell.exe -Command "Set-Clipboard -Value \$input"
Remember to escape the $
with a slash because $input
is a variable in PowerShell. If not, Linux would substitute it before running powershell.exe
and it would be the wrong value.
We can now finally both copy and paste inside WSL. But since we'd rather not type long and hard-to-remember commands over and over, we'll define aliases in the Linux shell. This is done with the alias
command:
alias pbcopy='powershell.exe -Command "Set-Clipboard -Value \$input"'
alias pbpaste='powershell.exe -Command "Get-Clipboard"'
At last, we've arrived back where we began in Getting Started. With the help of PowerShell, WSL, Linux, and just two lines of code, we now have commands for copying and pasting in the Linux shell.
Conclusion
Manually copying and pasting in the terminal is fraught with problems and annoyances. Clipboard command-line tools avoid many of these issues and integrate nicely with other tools. macOS comes with the built-in pbcopy
and pbpaste
commands, but getting the same functionality when running a Linux shell with WSL isn't as obvious. In this article, we created similar commands for WSL as command-line aliases.
A big advantage of clipboard command-line tools is being able to copy from and paste to other commands using pipes, and to and from files using redirects. Pipes make it trivial to connect clipboard commands to most command-line tools, such as gh
for creating Gists from the clipboard, or uuidgen
for copying random UUID values.
I hope pbcopy
and pbpaste
will help improve your everyday terminal workflow, just as they have for me. Either way, hopefully, this article shed some light on how to integrate Windows and Linux tools using the features of WSL, and inspired you to explore more ways to enhance your terminal experience.
Photo by Jo Szczepanska on Unsplash
Top comments (1)
Hi again and thanks for reading my first post to dev.to!
While I was working on this article, I found some slight problems with the aliases regarding how Windows and PowerShell deal with newlines. Most of the time, it probably doesn't even matter, but in some instances it may has a big impact, so I didn't want to leave it out. If you're doing something where it's important the pasted string exactly matches the copied data, like when computing a hash, there are some issues you need to be aware of.
First of all, Windows uses a different character sequence for newlines than Linux and other Unix systems. In Windows, a newline is represented by the "carriage return" character followed by "line feed", which is often represented as
CRLF
, or\r\n
in many programming languages, such as Bash shell scripting. Linux on the other hand just uses the "line feed" character, otherwiseLF
or\n
.When using
Get-Clipboard
, newlines always seem to be converted to Windows-style newlines, which might be a problem in some cases. One idea is to use the-Join
operator in PowerShell to change the characters used when joining the lines together. This would look something like this:Secondly, by default PowerShell always seems to add a newline to the end of the output. The best solution I've come up with is to pipe the output of
Get-Clipboard
toWrite-Host
together with the-NoNewLine
flag:However, I'm not sure if this always works exactly as expected, it might strip the ending newline even when the copied string ends with a newline.
You can combine these commands together, but apparently, there is a way to do both with just
Write-Host
:There may still be some issues, for instance when working with binary data, where both the
CRLF
andLF
character sequences could coexist in the same string and have to be preserved. I'm not entirely sure if it's possible to work around this problem, maybe by invoking C# functions for copy and paste instead.I'd be grateful if somebody with better PowerShell skills than mine (which are pretty lacking) could provide some feedback. And if anybody is interested in an elaboration on the issues, I could do that too. Once I understand the problem better I would like to update the article or write a follow-up.