# Shell tips The _shell_ is a **command line interpreter**. To use it you can open a _terminal_ (sometimes called a _console_). This is how most terminal windows look like: ![An example shell window](../images/shell-screenshot.png) If you haven't used it before, you should probably take a look at [this tutorial](http://linuxcommand.org/lc3_learning_the_shell.php). If you're using Windows, [these videos](https://www.youtube.com/playlist?list=PL6gx4Cwl9DGDV6SnbINlVUd0o2xT4JbMu) may be useful too, but keep in mind that the following tips only apply to Linux/macOS environments (Unix shells). You can also use a tool, for example [Cygwin](https://www.cygwin.com/), to have a Unix-like shell on Windows. ## The prompt (`$`) When searching Google, or Zulip's docs, you'll find commands that begin with a dollar sign `$` or a dollar sign preceded by some text (e.g., `(venv)john@laptop:~$`). This is called the **prompt**, and it's only an indicator that the shell is awaiting new orders. The prompt can contain useful information, let's look at `(venv)john@laptop:~$`: - `(venv)` informs the user that they're currently in a virtual environment (more on [Python virtual environments](https://docs.python-guide.org/dev/virtualenvs/)) - the `john` before `@` is the username - the `laptop` is the host machine name - the `~` after the colon informs the user they're currently in the home folder of the user `john` You shouldn't type the prompt or the text preceding it, since it isn't a part of the commands. ## Tilde character (`~`) It's very frequent to see the tilde (`~`) in paths. The tilde is an abbreviation for your home directory (`/home/YOUR_USERNAME` most of the times). That's why the following is exactly the same, if the user running it is `john`: ```console $ cd ~ $ cd /home/john ``` ## Change directory (`cd`) When you're using the shell, you work inside a directory (the one specified in the prompt). This way you can point to files relative to your current directory, instead of writing the whole path. Imagine you have a file called `ideas.txt` inside `/home/john/notes/`, and you want to edit it using `nano`. You could use: ```console $ nano /home/john/notes/ideas.txt ``` However, that isn't very practical, especially if you are working with longer paths. That's why it's very useful to change the path where you are currently located (usually known as **working directory**). To do that, you use `cd` (**c**hange **d**irectory): ```console $ cd /home/john/notes/ ~/notes$ nano ideas.txt ``` Or, if you're the user `john`: `cd ~/notes`. You can now access to all the files inside `/home/john/notes` directly, without needing to type the whole path. Relative paths make it much easier to move through files and directories, too. ## Running commands as root (`sudo`) You may have noticed that many commands begin with `sudo`. This informs the shell that the following command must be run as the root - a user that by default has access to all commands and files on a Unix operating system (i.e. a user with administrator privileges). That's why you may be asked for a password in those cases: the system verifies you have permission to act as the _root_ user. In case you were wondering, the name `sudo` comes from **s**uper **u**ser **do**. ## Escaping characters Some characters cannot be used directly in the shell, because they have a special meaning. Consider the following example: ```console $ echo "He said hello" He said hello ``` What if you wanted to display double quotes? You can't use `echo "He said "hello""`, because in that case you're using the double quotes for two different purposes: - Delimiting the string you want to use, from `He` to `"hello"`. - Quoting something, by literally printing `"`. You have to specify which double quotes are used in each case. When you want one of those "special characters" to be literally printed, that's called **character escaping**. To escape a character, simply add a backslash (`\`) before it. Returning to our example: ```console $ echo "He said \"hello\"" He said "hello" ``` As you can see, the double quotes with the backslash are shown, but the ones without it are used as string delimiters. Double quotes aren't the only case of special characters. Some others are `$`, `#`, `{` or `}`, but there are many more. The backslash itself can be escaped as well, using the same procedure: `\\`. ## Sequencing commands It's also possible to run multiple commands in a single line. For that purpose, the shell provides two different separators: - **Semicolon `;`**: runs a command, and once it has finished, runs the next one: ```console $ echo "Hello"; echo "World!" Hello World! ``` - **Double ampersand `&&`**: runs a command, and **only if** it finished without errors, it proceeds with the next one: ```console $ qwfvijwe && echo "Hello" qwfvijwe: command not found ``` Notice that it doesn't print `Hello` at the end, because the previous command (`qwfvijwe`) returned an error. When using an incorrect command with a semicolon, the `Hello` will still be printed: ```console $ qwfvijwe; echo "Hello" qwfvijwe: command not found Hello ``` ## Splitting commands into multiple lines Sometimes you end up with a very long command, that is hard to read and may be unclear. This is a problem, especially if you want to share that command, e.g., in a documentation file. In those cases, you can use a backslash at the end of each line, to inform the shell "wait, there's more on the next line". This is an example, taken from the docs on how to install the Zulip development environment: ```bash sudo apt-get -y purge vagrant && \ curl -fLO https://releases.hashicorp.com/vagrant/2.0.2/vagrant_2.0.2_x86_64.deb && \ sudo dpkg -i vagrant*.deb && \ sudo apt-get -y install build-essential git ruby lxc lxc-templates cgroup-lite redir && \ vagrant plugin install vagrant-lxc && \ vagrant lxc sudoers ``` It's all a single command, joined using the double ampersand explained in [Sequencing commands](#sequencing-commands). If you're typing it manually, you don't need to include the backslashes, just write it all on the same line, and hit ENTER/RETURN at the end. If you think about it, what is happening here is actually another case of character escaping. The newline character (the one that appears when you hit ENTER) usually means "read this command". However, here we want to literally have the newline character, and thus the `\`. The newline character is invisible (we only see a line break), but it's still there! ## Arguments Most commands need additional data to work, like a path or a file. That extra information is called an **argument**, and it's specified after the name of the command, like this: ```console $ cd /home/john/notes ``` Here, the command is `cd`, and the first (and only) argument is `/home/john/notes`: - `cd` - _command_: changes your current directory. - `/home/john/notes` - _argument_: the directory where you want to go. In each command the arguments are specified in different ways, and have different meanings. Sometimes, a command can accept arguments indicated with dashes. Here's another example of arguments usage: ```console $ nano -C /home/john/backups --mouse todo.txt ``` As you can see, some arguments imply that more information has to be specified, while others don't. In this case, we're saying: "Bash, use the app `nano` to open the file `todo.txt`, enabling mouse support, and saving the backup files to `/home/john/backups`". The different parts are: - `nano` - _command_: program that allows editing text easily. - `-C` - _argument_: needs you to indicate where the backups should be stored, and thus you have to add an additional argument after it, to specify the directory (`/home/john/backups` in the example). - `--mouse` - _argument_: is just an option you set, `nano` doesn't need anything else to make it work. Thus, there isn't any extra argument for that. Note that the `todo.txt` is the file we want to open! It has nothing to do with the previous argument. This will probably clarify it (taken from `nano`'s help): ```console Usage: nano [OPTIONS] [FILE]... ``` So, in the options you indicate the arguments, and `FILE` is... well, the file. Don't worry, you don't have to memorize the meaning of all the arguments for every single command. There are [tools](#understanding-commands) that help you with that :wink:. ## Shebang You can run some files directly, without specifying a program to interpret them. That's why you may have seen cases, in the Zulip codebase or elsewhere, when some Python scripts are called with `python`: ```console $ python my_program.py ``` While other times, `python` isn't used: ```console $ ./my_program.py ``` In the latter case, the operating system will look at the beginning of the script to identify what interpreter (like `python` in this example) to run it with. The note telling the OS how to interpret the file goes on the file's very first line, and it's called a **shebang**. In our Python scripts, it looks like this: ```python #!/usr/bin/env python3 ``` With this, you're telling the operating system: "if I tell you to run this, ask `/usr/bin/env python3` how to understand it". The result is that the operating system is asked to run the script, it runs the command specified in the shebang, with the script filename added as a command-line argument. So, returning to our example with `my_program.py`, when you run `./my_program.py`, what happens under the hood is equivalent to: ```console $ /usr/bin/env python3 ./my_program.py ``` The purpose of `/usr/bin/env` in our shebangs is as a way to locate the `python3` program in your current environment, the same one the shell would use if you ran `python3 my_program.py`. You may see Python scripts outside of Zulip with a shebang like `#!/usr/bin/python3`; but because of the way Python virtualenvs work, this has the effect of running the script outside of any currently activated virtualenv. We use `/usr/bin/env` to keep our scripts running inside the virtualenv where we've installed all our dependencies. Another example of a shebang is the one used in Bash scripts. In those cases, `#!/bin/bash` or `#!/bin/sh` is used. ## Understanding commands Frequently, you may find commands that you don't understand, or don't know what they do. You can use `man ` to see the **man**ual page for that specific command. Also, you may find useful [explainshell](https://explainshell.com/), a webpage that explains what most commands do, part by part. Finally, [docopt](http://docopt.org/) can help you understand the syntax used by command-line tools to describe their interface, and make sense of strings like `cd: usage: cd [-L|[-P [-e]] [-@]] [dir]`). ## Cheatsheet There are many more commands in the shell, besides the ones explained in this file. [Here](https://www.git-tower.com/blog/command-line-cheat-sheet/) you can find a simple yet useful cheatsheet, created by Tower, that could help you understand and remember what other common commands do (e.g., `ls`). ## Git Probably at this point you've heard about Git. It's basically a tool that most developers use to manage all the changes in their code. At first it seems like magic, but once you get the basic concepts you find it extremely useful and even easy to use (at least the 99% of the time). To learn more about how to use it, read [our docs](../git/index.md) on Git and GitHub. [This cheatsheet][git-cheat-detailed] will be useful in your journey, as well. ![Git - XKCD 1597](https://imgs.xkcd.com/comics/git.png) [git-cheat-detailed]: ../git/cheat-sheet.md#detailed-cheat-sheet