DEV Community

Stefan Judis
Stefan Judis

Posted on • Originally published at stefanjudis.com

How to run copied CLI commands with a leading "$" sign

Use at your own risk. 🤓 Before implementing any functionality that makes running copied code easier, be aware that the internet's a bad place. There's always a chance that a command has malicious intent or even includes hidden commands.


I just saw an npm package that makes copying and pasting of shell commands easier. Documented shell commands often include a leading $ character (e.g. $ npm install whatever) to signal that the code block is a shell command. And when you're like me, you always copy and paste the $ sign with the command, leading to a command not found: $ error in your terminal.

Shell session: $ npm install whatever / zsh: command not found: $

And while it's not a huge deal, you have to either carefully copy the command not to include the $ sign or paste the command into your terminal and remove the dollar manually. There has to be a better way...

... and that's where the mentioned npm package comes into play. The package provides a global $ command that behaves like a proxy on your command line. The $ command simply runs all passed-in arguments.

$ echo "hello world" leads to an executed echo "hello world". $ ls is basically the same as ls. You get the idea. 🙈

This command is one of these tiny adjustments that makes a terminal feel like home. But what if I told you that you can create the same functionality without npm packages or Node.js using two lines of shell scripting? Read on!

Two lines to run commands with a leading $

Let's start by adding a new shell command to your system. Have a look at your $PATH configuration. The $PATH environment variable defines where executable files are located on UNIX systems.

That's the shortened version of my machine's $PATH. 👇

$ echo $PATH

/usr/local/bin:/usr/local/sbin:/Users/stefanjudis/bin:/Users/stefanjudis/.bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
Enter fullscreen mode Exit fullscreen mode

$PATH is a long string that separates all different locations by a :. And as you see, I have various bin directories. All my custom commands are placed in my home's .bin directory – ~/stefanjudis/.bin. I chose this location because I don't want to mix system and custom commands (ls, cat, etc. are located at /bin).

Choose a directory to place your new command.

$ pwd
/Users/stefanjudis/.bin

$ ll
.rwxr--r--  14 stefanjudis  8 Dec  2020 -- $
.rwxr-xr-x 413 stefanjudis  2 Aug  2020 -- git-delete-branch
.rwxr-xr-x 183 stefanjudis 19 May 22:03 -- git-pr-select
.rwxr-xr-x 538 stefanjudis 17 Dec  2020 -- git-select
Enter fullscreen mode Exit fullscreen mode

Create a new file named $ in this directory. Yep, that's right, this file doesn't include a file extension or something – it's really just a dollar.

Make sure the file is executable using chmod 755 $.

If you haven't used the chmod command before, make sure to read up on "UNIX file permissions".

The file's content is two lines:

#!/bin/zsh
exec "$@"
Enter fullscreen mode Exit fullscreen mode

The first line is called a Shebang and defines what program should be used to interpret this file when you run it as a standalone command. In my case, it's the zsh binary – #!/bin/zsh. #!/bin/bash works fine, too.

Then, exec "$@" runs and expands all the passed-in parameters. And that's all the magic already!

Make sure to include the quotes around $@ to avoid parameter expansions.

With this one file containing two lines, you can now run $ echo "hello world" and all these "dollar commands" in your terminal. 🎉

Terminal command: $ echo "hello world"

Happy copy and pasting!

Edit: Thanks to "okdjnfweonfe", Peter Franken and Joe Block for providing some feedback on the initial script. 🙇‍♂️

Top comments (5)

Collapse
 
unixorn profile image
Joe Block

If you make it exec $@, then your $ script will replace itself with the command, which will make it return the same exit code as the command you ran with it.

Your implementation will always exit 0 and suppress any exit code from what it runs, causing other scripts to think that things succeeded even when they fail.

Collapse
 
stefanjudis profile image
Stefan Judis • Edited

That's great feedback. Thanks Joe, I'll update and edit the post!

Collapse
 
pcjmfranken profile image
Peter Franken • Edited

Do not copy code straight into your terminal, and especially not from random blogs or embedded content! The website could have very easily loaded something else entirely from what it showed onto your clipboard.

Nasty stuff can and does happen which neither manually copying the snippet nor ZSH will protect you from. Check out this demo thejh.net/misc/website-terminal-co....

At the very least paste it into a plaintext/code editor (which TextEdit.app is not by default) or in your browser's address bar first to check if you're not being had.

If you enjoy gambling, though, and really must paste commands taken off the internet straight into your terminal, don't do so with elevated rights - meaning don't use sudo or enter passwords if you're asked for it until you've inspected the command first.

Collapse
 
stefanjudis profile image
Stefan Judis

Thanks. I'll added a note on top. :)

Collapse
 
noahholmes profile image
NoahHolmes

Sì, ho utilizzato il pacchetto npm. Tuttavia, ciò implica naturalmente l'installazione del pacchetto. Successivamente, è necessario configurarlo e attivarlo. È importante seguire la documentazione specifica del pacchetto, poiché le procedure possono variare. Questo può non essere molto conveniente. Al momento mi sono distratto dalla programmazione e mi sono appassionato ai giochi d'azzardo, dopo aver trovato un ottimo sito con informazioni su revoca autoesclusione AAMs tempi . Tuttavia, ho trovato il tuo post e ho sentito il desiderio di aggiornare le mie competenze di programmazione. Grazie per il tuo post!