Creating Shortcuts with Aliases and Functions

Bash lets you define your own versions of commands, either through aliases or functions.

Aliases let you create shortcuts for commands or override the default options for existing commands. You define them with the alias command, but it’s better to define them in your ~/.bashrc file. Let’s define some aliases.

Open your ~/.bashrc file in nano:

 $ ​​nano​​ ​​~/.bashrc

Let’s create an alias for ls -alh so you can avoid typing it out. Add this line to the end of the ~/.bashrc file to define an alias called ll:

 alias ll=​'ls -alh'

Save the file and exit the editor. Then source the file to apply the changes:

 $ ​​source​​ ​​~/.bashrc

Try running the ll alias:

 $ ​​ll
 total 124K
 drwxr-xr-x 15 root root 4.0K Mar 3 11:34 .
 drwxr-xr-x 4 root root 4.0K Mar 3 10:06 ..
 ...

You can use this any time you want a long listing.

You can make an alias for any command you’d like. Let’s add an alias to display your public IP address quickly. Open the ~/.bashrc file again:

 $ ​​nano​​ ​​~/.bashrc

Add this alias to the file which fetches your public IP address from an external website:

 alias myip=​'curl icanhazip.com'

You’ll learn how this command works in Making Web Requests with cURL.

Save the file, exit the editor, and then source the file to apply the changes to the current shell:

 $ ​​source​​ ​​~/.bashrc

Try out your new alias:

 $ ​​myip
 203.0.113.24

Aliases you create won’t be available if you use the sudo command.

Try it out:

 $ ​​sudo​​ ​​ll
 sudo: ll: command not found

By default, Bash doesn’t look beyond the first word for any aliases, but you can fix that by adding an alias for sudo. Open up the ~/.bashrc file again:

 $ ​​nano​​ ​​~/.bashrc

Add this alias to the file:

 alias sudo=​'sudo '

Note the space after sudo. By leaving a space as part of the command, Bash will look at the next word to see if it’s an alias, which means the ll alias will now work.

Save the file, exit the editor, and then source the ~/.bashrc file to apply the changes. Then try the command again. This time it works:

 $ ​​sudo​​ ​​ll
 total 96K
 drwxr-xr-x 15 brian brian 4.0K Mar 2 16:05 .
 drwxr-xr-x 3 root root 4.0K Mar 2 17:59 ..
 ...

As you can see from the sudo alias, you can use an alias to override a command with new behavior. So if you always want a long listing when you run ls, you can do that. Just define the alias ls like this:

 $ ​​alias​​ ​​ls=​​'ls -lh'

Now when you type ls, you’ll get the long listing:

 $ ​​ls
 total 36K
 drwxr-xr-x 2 brian brian 4.0K Mar 2 11:59 Desktop
 drwxr-xr-x 2 brian brian 4.0K Mar 2 11:59 Documents
 ...

But don’t worry; the old behavior is still available. All you have to do is prefix the command with :

 $ ​​ls
 Desktop Documents Downloads
 examples.desktop Music
 Pictures Public Videos

And you can remove the alias with the unalias command:

 $ ​​unalias​​ ​​ls

Aliases have some limitations. First, they’re really only designed to either redefine or point to a different command. Arguments you pass to an alias get forwarded along.

If you need more flexibility, you can define functions. Let’s explore this by creating a new function called mcd that creates a directory and navigates to it in a single command. You’ve probably wanted something like this every time you’ve created a new folder and had to navigate to it. Open the ~/.bashrc file in nano:

 $ ​​nano​​ ​​~/.bashrc

To declare a function, use the function keyword, followed by the name of the function and the function body, similar to how you’d define a function in many other programming languages. Add this to the file to define the mcd function:

 function ​mcd () {
  mkdir -p ​"​$1​"​ && cd ​"​$1​"
 }

The $1 variable is a reference to the argument passed to the mcd function when it’s called. It’ll be the name of the directory we want to create and switch to.

If you’re defining a small function like this, you can write it in only one line of code:

 mcd () { mkdir -p ​"​$1​"​ && cd ​"​$1​"​; }

Note the semicolon after the cd command. That’s necessary if you’re creating a one-line function. Another difference here is that this definition doesn’t use the function keyword. You don’t actually need the function keyword when defining a function. whether it’s simple or complex, but it’s easier for others to follow what you’re doing if you use it, so I recommend including it.

Save the file, exit the editor, and source the file with source ~/.bashrc. Then try it out:

 $ ​​mcd​​ ​​~/testdir
 $ ​​pwd
 /home/brian/testdir
 $ ​​cd

You can make more complex functions than this. Let’s create a function that displays info about your environment. You’ll use the uname -a command to get OS info, the free command to display available memory, and you’ll use curl icanhazip.com to fetch your public IP address. You’ll then use echo with the -e flag to preserve new lines so you get a nice-looking output.

Open your .bashrc file:

 $ ​​nano​​ ​​~/.bashrc

Add this function to the file:

 function ​showme () {
  echo ​"OS:"
  uname -a
  echo -e ​"​​ ​​Uptime:"
  uptime
  echo -e ​"​​ ​​Memory:"
  free
  echo -e ​"​​ ​​WAN IP :"
  curl -s icanhazip.com
 }

If you want to try this on macOS, replace the free command in this function with top -l 1 -s 0 | grep PhysMem, as macOS doesn’t have the free command.

Save the file, exit the editor, source your .bashrc file, and run the command:

 $ ​​showme
 OS:
 Linux puzzles 4.18.0-15-generic ​#16~18.04.1-Ubuntu SMP Sun Mar 3 14:06:04
 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
 
 Uptime:
  17:46:48 up 18:13, 1 user, load average: 0.08, 0.02, 0.01
 
 Memory:
  total used free shared buff/cache available
 Mem: 2041112 1059040 241124 47652 740948 775436
 Swap: 483800 5388 478412
 
 WAN IP :
 203.0.113.24

You can put all sorts of logic inside of these functions, including conditional statements.

Let’s make a function named less that overrides the real less command. When you call less and pass it a file, you’ll display the file with line numbers. If you pipe data to the less command from another program, you’ll keep the original behavior. It sounds a little like an alias, but by using a function, you can add logic to see how the function was invoked and specify different options depending on whether it’s called directly or if it’s receiving data from standard input.

To do this in a somewhat naive way, you’ll check to see if the standard input stream is connected to a terminal. In other words, you’ll check to see if the input is coming from a command the user typed, rather than from another program.

The expression [ -t 0 ] is how you test that file descriptor 0, or standard input, is connected to your terminal. You can use if-else statements in your functions to evaluate boolean expressions like this. Here’s how that looks:

 if​ [ -t 0 ]; ​then
 # input is interactive
 else
 # input is coming from a pipe
 fi

So, to make the less command show line numbers unless you pipe data, add this function declaration to your ~/.bashrc file:

 function ​less() {
 if​ [ -t 0 ]; ​then
  ​command less -N ​"​$@​"
 else
  ​command less ​"​$@​"
 fi
 }

Now, when you call less, you’re not calling the actual less program; you’re calling this function. This function will then test to see if the input came from the connected terminal or from a pipe. If it came from a connected terminal, it calls the actual less command with the -N option, enabling line numbers. $@ refers to all of the arguments you passed to less when you invoked it. Notice that we use command less inside the function. This ensures that we’re calling the actual less command. This is a safe way to wrap built-in commands with your own functions to extend their behavior.

Save your ~/.bashrc file and apply the changes using source ~/.bashrc. Now try it out by using less to view a file. You’ll have it display the nano.html file you created earlier in this chapter:

 $ ​​less​​ ​​nano.html
  1 <!DOCTYPE html>
  2 <html lang="en-US">
  3 <head>
  4 <meta charset="utf-8">
  5 <title>Nano</title>
  6 </head>
  7 <body>
  8 <p>I made this in nano</p>
  9 </body>
  10 </html>

Press q to quit less and return to the prompt.

Now invoke less by sending data to your less function through standard input:

 $ ​​less​​ ​​<nano.html
 <!DOCTYPE html>
 <html lang="en-US">
  <head>
  <meta charset="utf-8">
  <title>Nano</title>
  </head>
  <body>
  <p>I made this in nano</p>
  </body>
 </html>

This function demonstrates how you can add conditional logic, but it’s not a perfect test. In some situations it won’t give you the behavior you want because the test will think you are using a pipe, such as when used in command substitution.

You’ll learn about command substitution in the next chapter.

Since this function has some side effects, you should remove it from your ~/.bashrc file before moving forward, or rename it so it doesn’t conflict with the built-in less command and surprise you later.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.240.75