• Tidak ada hasil yang ditemukan

Learning Shell Scripting with Zsh

N/A
N/A
Protected

Academic year: 2019

Membagikan "Learning Shell Scripting with Zsh"

Copied!
132
0
0

Teks penuh

(1)
(2)

Learning Shell Scripting

with Zsh

Your one-stop guide to reading, writing, and debugging

simple and complex Z shell scripts

Gastón Festari

(3)

Learning Shell Scripting with Zsh

Copyright © 2014 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

First published: January 2014

Production Reference: 1080114

Published by Packt Publishing Ltd. Livery Place

35 Livery Street

Birmingham B3 2PB, UK.

ISBN 978-1-78328-293-7

www.packtpub.com

(4)

Credits

Author

Gastón Festari

Reviewers Takeshi Banse

Alice Ferrazzi

Chien-Wei Huang

Acquisition Editor Rubal Kaur

Commissioning Editor Govindan K

Technical Editors Nikhil Potdukhe

Tarunveer Shetty

Copy Editors Dipti Kapadia

Kirti Pai

Project Coordinator Aboli Ambardekar

Proofreader Bridget Braund

Indexer

Hemangini Bari

Production Coordinator Alwin Roy

(5)

About the Author

Gastón Festari

is a scripting language enthusiast with over five years of experience and a firm believer in free, open source software. Currently working as a developer for Globant, he likes to spread the word about zsh at different meetups and events when away from the keyboard.

The number of people who deserve their name on this page for making this possible would require a book of its own, so allow me to start by apologizing if your name isn't here by saying: I owe you a hug and a big "thank you".

To my grandparents and my family for allowing me to follow my ambitions. My friends, Xeba and his wonderful family, Mathías and Eliana, Bruno, Lore, Ce, and Dan for putting up with this project of mine. Without your encouragement and support, this could have never been completed.

My colleagues, particularly Gabriel, Diego, and Ale, for their feedback and for getting me through those particularly difficult times around Chapter Four. To the technical reviewers Alice Ferrazzi, Chien-Wei Huang, and Takeshi Banse; and staff at Packt Publishing for their great suggestions and eagle-eyed corrections.

So now you know, if you don't see your name in here, come by with a frowning face, and you'll get that much-deserved hug. I promise.

(6)

About the Reviewers

Takeshi Banse lives in Tokyo, Japan. He likes to write code for Linux. His e-mail

address is takebi@laafc.net.

Alice Ferrazzi has been using zsh since 2011. She is currently living in Tokyo,

studying Japanese at Tokyo Central Japanese Language School (TCJ) in the morning and working at MIRACLE LINUX in the afternoon.

She contributes to Gentoo and open source software in her free time. She has a wiki at http://aliceinwire.net.

Thanks for everyone's support and encouragement.

(7)

www.PacktPub.com

Support files, eBooks, discount offers and more

You might want to visit www.PacktPub.com for support files and downloads related to your book.

Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub. com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at service@packtpub.com for more details.

At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.

http://PacktLib.PacktPub.com

Do you need instant solutions to your IT questions? PacktLib is Packt's online digital book library. Here, you can access, read and search across Packt's entire library of books.

Why Subscribe?

• Fully searchable across every book published by Packt • Copy and paste, print and bookmark content

• On demand and accessible via web browser

Free Access for Packt account holders

(8)

Table of Contents

Preface 1

Chapter 1: Getting Started

7

Installing zsh 7

Installing on Linux 8

Installing on OS X 9

Compiling from source 10

First run 10

Making zsh your login shell 12

Shell options 13

The startup files 14

The shell prompt 16

The prompt command 17

Customizing the prompt 18 Using escape sequences 19 Conditional expressions 22 Putting it all together 22

Summary 25

Chapter 2: Alias and History

27

Working with aliases 27

Quoting characters 29

Single and double quoting aliases 30

Global aliases 33

Hashes 34

Putting it all together 35

Expansion 36

Parameter expansion 36

(9)

Table of Contents

Chapter 3: Advanced Editing

49

Zsh line editor 49

Getting to know ZLE 50

Working with keymaps 50

Basic editing 51

Going back and forth with words 52

Yanking and transposing text 52

Revisiting history 54

Advanced editing 55

ZLE-related options 55

Defining your own keymaps 56

Don't call them widgets 59

Defining your own widgets 60

Your first function 62

Working with regions 65

Multiline editing 65

Putting it all together 67

Summary 68

Chapter 4: Globbing 71

Quoting your strings 71

Double quotes 73

Getting started with Globbing 74

Globbing with the stars 74

Questions for any single character 76 Brackets for a sequence of characters 76 Using safer ranges on your scripts 77

(10)

Table of Contents

[ iii ]

Glob qualifiers 85

Timestamp qualifiers 87

File size qualifiers 88

The zmv function 88

Summary 90

Chapter 5: Completion 91

Getting started with completion 91

Getting assertive with zstyle 93

Command correction 95

Completers 97

Ignoring matches 98

Function definitions 99

The path of the function 101

Summary 105

Chapter 6: Tips and Tricks

107

Main resources 107

Helping tips 108

Directory substitution 108

Magic space 108

Random numbers 109

zcalc 109 Change and list directory contents 109 Finding your path through commands 110

Other projects 111

zsh-lovers 111

zsh-users 111

oh-my-zsh 111

Prezto 112

Explain Shell 112

Your dotfiles 112

Summary 113

(11)
(12)

Preface

If I had to take a wild guess, I'd say that you are reading these lines because, like me, you spend quite some time dealing with Unix systems. Be it because your job requires you to, or you simply love to poke around an operating system's internals, the shell is arguably how you deal with most of your activities.

Historically, shells were conceived for speeding up our work, but we all know that at some point, what was supposed to be a leaner way to get things done turned into a slugfest of arcane symbols and impossibly long-to-remember lines of code.

Wouldn't it be great then, if we could squeeze just a bit more out of our system? Imagine the things you are currently doing and being able to do them in a more efficient, elegant way, even the things that you thought were some sort of magic that only Linux's wizards with centuries' worth of experience were able to perform.

What if I told you that feats such as knowing which option flags are available to a program no longer require you to scan endless screens of manpages? Imagine not having to deal with journeys along infinite horizontal lines of characters anymore. And what about relying on automatic completion instead of typing the same lines again? What if knowing which directory you are currently working on merely required you to stare at your command prompt? Now imagine that all it takes for getting started with all of this only demands you to switch to a new shell.

What this book covers

Chapter 1, Getting Started, starts from scratch by explaining how to install and set up zsh. Learn about startup files and customizing the shell prompt.

(13)

Preface

[ 2 ]

Chapter 3, Advanced Editing, introduces zsh's Line Editor and working with the various shortcuts and key bindings on the command line.

Chapter 4, Globbing, introduces the new ways of working with the system's files and directories by applying parameter substitution and modifiers to deal with all kinds of tasks.

Chapter 5, Completion, introduces you to one of zsh's greatest features and shows you how to start tweaking "the new" completion system by defining your own styles and functions.

Chapter 6, Tips and Tricks, explains miscellaneous settings and configuration options that are definitely worth trying, together with some cool community projects that should be on your radar.

What you need for this book

Before getting started, you should be comfortable in handling a terminal emulator. Most operating systems bundle such software within their stock set of applications, but as is the case with any application, there are other offerings out there waiting to be discovered. Such alternatives are probably even better suited for the task at hand, so please make sure you get to know the ins and outs of your weapon of choice and its quirks before jumping into this book.

Also required for following this text and the provided examples is the Git source code management system. It can be easily obtained and installed by following the instructions provided at http://git-scm.com, and it's an indispensable tool when attempting to use some of the various software projects and sources mentioned throughout this book.

Who this book is for

(14)

Preface

[ 3 ]

Conventions

In this book, you will find a number of styles of text that distinguish between different kinds of information. Here are some examples of these styles, and an explanation of their meaning.

Code words in text are shown as follows: "This alias changes the behavior of ls by calling it with the color flag every time you type it, instead of using its more vanilla version."

A block of code is set as follows:

zstyle ':completion:*:descriptions' format '%B%d%b' zstyle ':completion:*:messages' format %d

zstyle ':completion:*:warnings' format 'No matches for: %d'

When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:

autoload -Uz compinit

compinit

Any command-line input or output is written as follows:

$ zsh --version

zsh 5.0.2 (x86_64-apple-darwin12.3.0)

New terms and important words are shown in bold. Words that you see on the screen, in menus or dialog boxes for example, appear in the text like this: "Should your operating system greet you with a polite zsh not found message, that's ok though; otherwise, you won't be reading these lines."

Warnings or important notes appear in a box like this.

(15)

Preface

[ 4 ]

Reader feedback

Feedback from our readers is always welcome. Let us know what you think about this book—what you liked or may have disliked. Reader feedback is important for us to develop titles that you really get the most out of.

To send us general feedback, simply send an e-mail to feedback@packtpub.com, and mention the book title through the subject of your message.

If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide on www.packtpub.com/authors.

Customer support

Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Errata

(16)

Preface

[ 5 ]

Piracy

Piracy of copyright material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works, in any form, on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy.

Please contact us at copyright@packtpub.com with a link to the suspected pirated material.

We appreciate your help in protecting our authors, and our ability to bring you valuable content.

Questions

(17)
(18)

Getting Started

So, what's the deal with Z shell? You probably have a solid notion of what to

expect from a modern shell, so things such as command history, completion, and autocorrection will not wow you as much as someone who just discovered Bash. However, unlike some of the other available shells out there, Z shell (zsh) boasts of a really powerful scripting language and an incredible completion system. Actually, incredible doesn't even begin to describe it. Swift and effortless sounds a bit more appropriate. Zsh also incorporates—and arguably, improves on—many of the useful features of Bash, ksh, and csh, even going so far as to allow you to emulate these shells in your scripts for an extra layer of compatibility.

Once you discover things such as multiline editing or start relying on automatic spell correction though, I promise you will look back at your old days of keyboard mashing buttons and wonder why you didn't make the switch sooner. So let's get started with it, shall we?

In this chapter, we will start by getting to know zsh, with a quick glimpse at some of the features that make it unique. Before we embark on our adventure though, we will need to install and configure our new shell, so we can ensure everything is up and running smoothly. We then move on to the configuration—what are the startup files, and how to use the different styles, escape sequences, and conditional expressions in order to customize the prompt.

Installing zsh

(19)

Getting Started

[ 8 ]

Before getting started, it would be a good idea to check whether you will need to install or update your current installation of zsh, as the package could already be installed on some Unix systems. So, open up your favorite terminal emulator and type in the following command:

$ echo $SHELL

This should print out something like /bin/sh or /bin/bash on most systems, and this means that your current login shell is something other than zsh. If you see zsh in the result though, go ahead and call the following commands:

$ zsh --version

zsh 5.0.2 (x86_64-apple-darwin12.3.0)

With some luck (and a healthy regime of system updates on your side, of course), you should see zsh's version, something that pretty much resembles the previous snippet. If that's the case, you can go ahead and skip this section. Should your operating system greet you with a polite zsh not found message. That's ok though, otherwise you wouldn't be reading these lines. Let's get into the installation part of the deal, shall we?

We'll use the latest stable release—version 5.0.2 as at the time of writing this book—as a reference in this book. So it is advisable to try and update your current installation if you are running a previous release. Refer to your package manager's documentation in order to update zsh.

Installing on Linux

Depending on which distribution of Linux your PC is currently sporting, zsh might (or might not) be in its repositories or, better yet, already installed on your OS. You should always refer to your OS's package listing in the rare event that zsh is unavailable.

On Debian and its multitude of derived distributions—such as Ubuntu and Linux Mint—you could get the whole installation process completed by simply opening a terminal and running the following commands:

$ sudo apt-get update $ sudo apt-get install zsh

(20)

Chapter 1

[ 9 ]

You can always check the version of zsh by running zsh --version in the terminal.

Red Hat-based distributions such as Fedora will need you to input the following commands:

$ sudo yum check-update $ sudo yum install zsh

Then, there are the openSuSE users:

$ sudo zypper refresh $ sudo zypper install zsh

And let's not forget the Arch users:

$ sudo pacman -S zsh

Wait for the download and installation scripts/triggers to complete, go ahead, and skip to the next section.

Installing on OS X

Arguably, the easiest way to get your hands on zsh in OS X is either via

Homebrew (http://www.brew.sh) or MacPorts (http://www.macports.org), package managers that aim to extend the default options available to OS X users. Unfortunately, neither of these options come bundled with OS X. You will need to install either of the solutions before you can go ahead and make do with the latest version of zsh (which remains 5.0.2 at the time of writing this book). So, open your terminal emulator of preference, and either type:

$ brew install zsh

or

$ sudo port install zsh

(21)

Getting Started

[ 10 ]

Compiling from source

The official home for zsh is located at zsh.sourceforge.net, and this is where you should point your browser in order to get started with your building adventure. Keep in mind, though, that the recommended way of obtaining a zsh binary for your system is via the compiled binaries packages. If for some reason, however, you just want to get the latest and greatest and don't mind dealing with more bugs than those of a stable release, you most likely will need to clone the repo using the Git version control software:

$ git clone git://git.code.sf.net/p/zsh/code zsh

Make sure you check-out and track the master branch, which is where the latest goodies have been committed. Also, keep in mind that there are some dependencies that need to be met before you can build your fresh local copy of zsh. These are all well-documented in the many configuration files that have been cloned into your disk, so take a long, hard look at the README file before you attempt things such as building the configure script.

Installing Git on your platform of choice goes beyond the scope of this book, but be rest assured that you won't have trouble following the instructions at http://www.git-scm.com.

First run

Now that zsh is on your system, how about we take it for a spin? Go ahead and open your terminal emulator of choice and call the following command:

$ zsh

(22)

Chapter 1

[ 11 ]

In order to avoid having to skip the configuration options on each subsequent run, you can go ahead and create what is known as a startup file:

% touch ~/.zshrc

We just created our main preferences file; the problem is, it stands empty as it is. Let's go ahead and add some preferences, shall we?

There will be plenty of references to zsh's options—the various settings that alter the shell's behavior—thus, now is as good a time as any to establish a couple of conventions. Firstly, the naming scheme is somewhat too forgiving—it is case-insensitive and ignores underscores and ignores underscores. As such, both the following option names mean the same.

SOME_OPTION and SOMEOPTION

Secondly, try to think of options as switches. As the name implies, they can either be turned on or off. Of the many ways that zsh provides to toggle its options, it is arguably easier to remember the setopt/unsetopt combo.

setopt SOME_OPTION # enables any option.

unsetopt SOME_OPTION # use this to disable an option.

Conversely, you can negate the behavior of an option by prepending NO

to its name, thus making unsetopt SOME_OPTION mean the same as

setopt NO_SOME_OPTION or, keeping in mind that underscores are only there for human readability, the same as setopt NOSOMEOPTION. Just for sanity's sake and because I do love me some standards, we'll use

ALL_CAPS_SNAKE_CASE for the options in this book.

Open ~/.zshrc with your favorite editor; you can use editors such as vim, Emacs, nano, or whatever kids find cool these days, and add the following line:

autoload -U promptinit # initialize the prompt system promptinit

Let's go over what we just typed: the first line of the code is our way to tell the shell to start its promptinit module—a series of functions that deal with handling the shell's various prompts and functionality. What you see right after the hash sign is just a comment to remind you of what the command is doing and why it is there. Finally, the last line is the one that actually calls and initializes the prompt module. It might not seem much, but it will come in handy when dealing with prompts, I promise.

(23)

Getting Started

[ 12 ]

Zsh will ignore each line that starts with a hash (#)—or pound—sign. This is really helpful for debugging preferences and, better yet, documenting your functionality. Consider the next example, with comments in bold:

# This is a comment and will be ignored by the shell.

HISTFILE=~/.zsh_history # sets the location of the history file

Making zsh your login shell

If there's something that shells take seriously, is their role. See, the thing with shells is that they like to hang out in very specific categories—they are either interactive or non-interactive, and then there are login shells.

As you might have guessed from their name, interactive shells allow you to interact with them; that is, they display a prompt, you enter a command, and they get back to you with an answer and a prompt that is ready for new input. On the other hand, Apply interactive shells get called to execute a script and go off their own merry way when the job is done.

Put simply, a prompt usually is the blinking cursor that tells you a shell is ready for you.

What about login shells then? Well, unlike interactive shells, login shells are usually called when the user performs a login—be it either on the local machine or when using tools such as SSH, for example—and takes the trouble to go through your startup files and configuration bits and pieces of the shell. More importantly, your login shell doesn't necessarily need to be interactive.

In the previous section, we used a direct call to the binary zsh to start zsh. As you can imagine, this is but a temporary workaround, as typing the name of the shell every single time we want to use it seems a bit impractical, to say the least. Even worse is the thought of having your previous shell lurking beneath and ready to jump back at you as soon as you're done with zsh. If you don't trust me, go ahead and type exit; I'll wait. See that thing that's on your screen? That's your former command-line companion right there. Say your goodbyes and hop back into zsh by typing zsh and pressing return.

(24)

Chapter 1

[ 13 ]

You can always trick zsh, and many other shells, into thinking it is a login shell by starting it with either the -l or --login flag. Open your

terminal and type either of the following commands:

$ zsh -l

or

$ zsh --login

Voilà! A shell with a login complex.

Luckily for us, the Unix chsh command seems to be just what the doctor recommended, so go ahead and type the following in your terminal:

$ chsh -s $(which zsh)

In the previous snippet, we're telling the system to change the shell for the current user. The option -s is used here to specify the location of the shell binary. That fancy $() construct you see there is our way of telling the shell to expand the result of the command within the parentheses, which is the result of the command which zsh. You might recall which from the previous section, when we required its services to figure out the location of our existing zsh installation. The job of which consists of shouting out loud the location of any program file in the user's $PATH environment variable. Thus, we can safely assume that if zsh is not there, something has taken a wrong turn somewhere and, perhaps, it's advisable to retrace our steps.

It's more than likely that changing your login shell will require it to run with elevated privileges, so make sure you are using an account with the appropriate permissions.

From now on, you'll be greeted by zsh by default on your system and every time you start your terminal emulator of choice. And likely so, you have installed and made zsh your login shell. Next up is tweaking it.

Shell options

(25)

Getting Started

[ 14 ]

Any of these options can also be set after the shell has been started; you simply have to call the desired option flag via the set command. The following example triggers the verbose mode on a running session:

% set -v

% echo 'quite the echo in here' > echo 'quite the echo in here' > 'quite the echo in here'

Downloading the example code

You can download the example code files for all Packt books

you have purchased from your account at http://www. packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register

to have the files e-mailed directly to you.

And, you can disable any option with the same set command and replacing the dash/minus sign with a plus sign as follows:

# disables verbose mode % set +v

More info regarding the various shell options and their usage can be found in the zshoptions(1) manpage (man zshoptions).

The startup files

Like most login shells, zsh relies on a series of configuration files known as startup files, which contain the commands and preferences to be executed and set during the shell startup routine. We used the .zshrc file in the previous sections to avoid being bothered by the newuser function, but now that we have made zsh our login shell, it's time we take a closer look at what we can do with them.

By default, zsh looks for startup files in the user's home directory,

$HOME (or its alias, the more popular tilde, ~. We'll alternate their use in this text as the path to the current user's home folder on the system), environment variable. You can tell zsh to look for your

configuration files in another folder by setting the parameter ZDOTDIR

to a directory of your choice in your .zshenv file under $HOME:

(26)

Chapter 1

[ 15 ]

During startup, zsh looks for, or sources, a very specific system and user set of filenames under /etc/. Right after this, each of these files have a user-editable doppelganger, typically located in $HOME, which gets read. There are some rules, however, that might make zsh skip some of these files altogether. The ordering of these files is really important, as setting an option in the wrong file can result in commands getting executed at the wrong time and some really funky behavior. Thus, try to keep in mind the following order when setting preferences on your files:

• zshenv • zprofile • zshrc • zlogin

If zsh is not called as an interactive shell, zprofile and zshrc together with their counterparts in $HOME (~/.zprofile and ~/.zshrc) will not be sourced. In addition, if zsh is not called as a login shell, zlogin and $HOME/.zlogin will also be skipped.

Depending on how you installed zsh, another directory besides

/etc/ can be used when looking for the global files.

Typically, you'd only like to mess with your own user's preferences, so we'll focus on the startup files that reside under $HOME, those are as follows:

• ~/.zshenv: This will be called immediately after /etc/zshenv. You should only add things such as the PATH settings and stuff you want to make available to any type of shell, whether it's interactive or not.

• ~/.zprofile: This is the companion to /etc/zprofile and kind of the boring guy out of the startup files bunch. You should put here any scripts you want executed before ~/.zshrc.

• ~/.zshrc: This is your workhorse. Most of your user settings and shell preferences end up here. Keep in mind it'll only be taken into account for interactive shells. As we'll see later on, you can declutter and expand its reach by sourcing multiple files.

(27)

Getting Started

[ 16 ]

On the opposite corner of the startup files, there are the shutdown files. As you can imagine, this relatively smaller set of files gets called not only in a specific order but also during the logout sequence of the login shell. The shutdown files can be considered a subset of the startup files, so there's no need to lose sleep over them. The important thing to remember is that when you type logout in the command line, the settings stored in the user configurable ~/.zlogout file are read, followed by the installation file /etc/zlogout.

You can use the options RCS and GLOBAL_RCS to disable the loading mechanism of the startup files. This preference has to be unset on the system file /etc/zshenv as follows:

unset RCS # disables loading of files other than zshenv

unset GLOBAL_RCS # disables loading of files under /etc/

For instance, if the RCS option is unset in zshenv (the first file that is read), ~/.zshenv and all the remaining files will be skipped. Keep in mind though, that both of these options can be turned on again by any subsequent file that you load.

For example, if you have the following in /etc/shenv:

unset RCS

source my_options_file.zsh

And then in my_options_file.zsh add:

# some more options here set RCS

Then, the shell will proceed and load .zshenv as if nothing happened. So, be careful! We have taken a look at the startup files and their somewhat strict ordering; now, it's time we get up close and personal with the prompt.

The shell prompt

(28)

Chapter 1

[ 17 ]

The prompt command

Zsh comes with a wide array of predefined prompt configurations that can be used as building blocks for something that more adequately meets your needs. Among other things, the utility prompt allows you to select your preferred theme. On a default installation, the various themes and user contributions are located under <zshFolder>/Functions/Prompts (or <zshFolder>/functions in OS X) and follow the naming scheme prompt_<theme>_setup. To have a look at what's included in the stock package, just type the following command:

$ prompt –p

And you should see a list of all the available prompt themes included with zsh. You can use the -p option together with a theme name to take a closer look at any of the themes:

$ prompt -p

In order to use the prompt function, you will need to set up the promptinit module on your shell. The easiest way to do this is to add it to your .zshrc file. Take a look at the section First run if you haven't done so yet.

You can refer to the PROMPT THEMES section under the

zshcontrib(1) manpage in order to get more in-depth information regarding prompts on zsh. Just type man zshcontrib in your terminal to get started.

You can test drive any theme you like, applying it temporarily to your current shell by typing:

$ prompt <theme_name>

Some themes, such as adam1, can even accept some extra configuration parameters like the following:

$ prompt adam1 red yellow magenta # sets the 'adam1' theme

By default, zsh won't be too fond of comments typed in the command line. Luckily, you can alter this behavior by setting the following option in your .zshrc file:

(29)

Getting Started

[ 18 ]

In the previous snippet, we are passing a list of options to the theme, namely the colors red, yellow, and magenta. You can get a more thorough description of what's allowed for each prompt theme by calling the built-in help on any given theme:

$ prompt -h <theme_name>

Try this on your favorite themes and see what else can be tweaked out of them.

Once you have found a combination that suits you, you can go ahead and

commit to those changes. Just open your .zshrc file with your editor and add the following line:

autoload -U promptinit promptinit

prompt adam1 red yellow magenta

We took our previous preferences file and sparkled some color in the default prompt adam1. So, how about we tweak it to make it feel more like home?

If you have invested a fair amount of time on customizing your prompt in your previous shell, it can be quite a headache trying to

figure out the different rules set, so it can be ported to zsh. Luckily,

zsh provides a series of tools for making the switch a more or less smooth experience. Located under <zshFolder>/Misc, you can use the bash2zshprompt or c2z scripts to migrate your Bash or csh preferences respectively. Note, however, that some distributions might

be missing this, in which case you should head straight to the official

repo and get your hands on a local copy. See the Compiling from source

section for more information on how to get the zsh source code.

Customizing the prompt

(30)

Chapter 1

[ 19 ]

$PS2 gets displayed whenever the shell is waiting for more input, such as at the start of some unfinished syntactic structure or when you add inline comments to the command line. $PS3 is used for making choices within a select loop control mechanism. Last but not the least, $PS4 really comes in handy for debugging scripts. Overall, these are the set of tools we will be working with, extending their

functionality beyond the basics with a nifty set of tools known as escape sequences.

You can use the source command to reload your zsh

configuration files at any time. Just save your changes and call the

following command:

$ source file_path/file_name

Remember to use double quotes if your file path includes spaces.

$ source "random folder/.zshenv"

Using escape sequences

Escape sequences are a set of predefined information shortcuts that can be added to zsh's prompt settings. They can show information such as the name of the machine to which you are logged on, the current date and time of the system, and even the current working directory. Most escape sequences are defined with a modulo or percent (%) operator, and some of them even take optional parameters to extend their functionality further.

For the magic to happen, however, we first need to add a new setting to our preferences file. Open .zshrc and add the following line:

setopt PROMPT_SUBST

By doing this, we're enabling the PROMPT_SUBST option. This will make zsh treat $PROMPT just as if it were a vanilla shell variable, and it will be checked against for command substitution, parameter and arithmetic expansion.

(31)

Getting Started

[ 20 ]

Shell state options

The following options serve as indicators for some aspects of the current state of the shell:

• %#: This displays # if the shell is running with elevated privileges and displays % otherwise

• %?: This shows the exit status code of the last command executed • %h or %!: This shows the current history event number

• %L: This displays the current value of the $SHLVL variable • %j: This prints the number of jobs being executed

Login information options

The following options display more useful information about the host and machine on which the shell is currently running:

• %M: This shows the machine's hostname.

• %m: Same as the previous. Hostname is printed up to the first dot (.)

separator. It takes an optional integer after % for the number of components to be displayed.

• %n: This will have the same effect as printing environment variable $USERNAME.

Directory options

The following options provide information regarding the path of the current working directory ($PWD) and filesystem directories:

• %d or %/: This shows the current directory. Works just as printing the $PWD environment variable.

• %~: Same as the previous, but if the current directory is $HOME, ~ is displayed instead.

• %c or %.: This lists the amount of directories trailing $PWD. It takes an integer as the parameter after %. Thus, %2c would show the two preceding directories to $PWD.

(32)

Chapter 1

[ 21 ]

Date and time options

The following options provide miscellaneous date and time information:

• %D: This prints the current system date in the yy-mm-dd format. • %W: Same as the previous but in mm/dd/yy format.

• %w: This shows the date in day-dd format.

• %T: This displays the current time of the day, 24-hour format. • %t or %@: Same as the previous, uses a 12-hour, am/pm format. • %*: Same as the previous, also displays seconds.

Text formatting options

Unlike the previous escape sequences, these need to be opened and closed around the desired part of the prompt. That is, in order to underline word, you need to type it as %Uword%u. Pay special attention to the difference in the case of the opening (UPPERCASE) and closing (lowercase) escape sequences, as shown in the following points:

• %U %u: This enables underline mode. • %B %b: This enables boldface mode.

• %K %k: This sets the background color. Use it as %K{red}%k. • %F %f: Like the the previous, but applies to the foreground color. • %S %s: This enables standout (highlight) mode.

When dealing with escape sequences, both % and ) are somewhat special as far as zsh is concerned; thus, remember to type %% if you need to display a literal % on your prompt. Likewise, a literal ) should be typed as %). This technique is commonly referred to as escaping characters.

You can enable the PROMPT_BANG option on your zsh configuration to

use a bang (!) in your prompt in order to display the current history event number instead of having to escape it (%!). Just remember to type

!!, should you require a literal !.

(33)

Getting Started

[ 22 ]

Conditional expressions

We will conclude our trip of the escape sequences by taking a look at the escape sequences available for conditional expansion. Luckily though, most of it can be summed up as the following ternary expression:

%(X.true-text.false-text)

Basically, what this means is that if the condition X is true, do whatever is in true-text, otherwise do whatever is in false-text. The important thing to remember is that you should wrap your expression with %(), and that the dots (.) you see there are completely arbitrary, meaning you can replace both of them with whatever character you like.

Regarding the true-text/false-text expressions, the manpage (as when you visit man zshmisc) tells us that they can be replaced with the likes of !. This will evaluate to true if the shell is running with privileges or ?, which in turn can be preceded by an integer n and will evaluate to true only if the exit status of the last command matches. Thus, in order to display # as your main prompt to signal whether you are running on elevated privileges, with a bit of imagination, you can come up with things like the following:

PS1=%(!.#.>)

Likewise, you could use the following line to wrap the exit status of the last command that was run, if it was other than 0, that is:

PS1=%(?..(%?%))

Putting it all together

As you are more than aware by now, zsh has many great features built in its prompt themes. So many in fact, that most of the time our custom solutions might feel like reinventing the wheel. We still need to take a shot at building our own prompt though; so, how about using one of the included themes as a starting point?

(34)

Chapter 1

[ 23 ]

What you see there is a shell function that goes by the same name as the file. A single call to this prompt_suse_setup function, with no parameters passed, is all that it takes to make two assignments—one for the PS1 prompt and the other for PS2. Have a look at the following code, which has been formatted for this example:

PS1="%n@%m:%~/ > " PS2="> "

So let's get started with hacking that prompt to pieces, shall we? Open your .zshrc file, and remember you will be adding the following line after the call to promptinit. We can start by highlighting the username, just like in the adam1 prompt:

PS1="%K{yellow}%n%k@%m:%~/ > "

If you recall from the previous section, the %K%k escape sequence defines the

background color. Highlighted in the code, we wrap the escape sequence, %n, to add some background color to the current session, $USERNAME. On the right-hand side of the @ symbol remains the short version of the machine name and some fancy line indicators, of course.

Let's add an error flag to the right-hand side, so we can check immediately for an abnormal command exit code:

RPS1="%(?..(%?%))"

If you feel like it, you can test our brand-new right-hand prompt by calling a program in a way that will end abnormally. Remember, an exit status of 0 is ok; everything else will trigger our prompt. Something such as ls some_nonexistent_ folder should be enough:

gfestari@machine:~/ > ls nonexistent_folder

ls: cannot access nonexistent_folder: No such file or directory gfestari@machine:~/ > (2)

You can sparkle some color into our right-hand prompt like we did for PS1. When you are done with your tweaking, try to leave .zshrc resembling the following code as much as possible:

autoload -U promptinit promptinit

PS1="%K{yellow}%n%k@%m:%~/ > " PS2="> "

(35)

Getting Started

[ 24 ]

We left the autoload -U promtpinit and promptinit calls in the previous example, so the prompt module would be loaded and ready for use, should you eventually require its services. Note, however, that you do not require both these calls unless you are planning on using the prompt module.

Save your file and let's reload zsh configuration. We do this by sourcing the .zshrc file one more time. Be careful though as this could take a while depending on the links to other files you might have added:

% source ~/.zshrc

source has a leaner and meaner brother: the dot (.) alias. Now that you've met him, feel free to do things such as the following:

% . ~/.zshrc

How about we take advantage of the whole width of the terminal emulator's window? You know, because widescreen.

A particularly useful on-screen help is the current directory shortcut, which if you recall can be either %~ or %d. So, how about we add a bit more context information to that lazy right-hand side prompt?

RPS1=%~

Come on, I know you didn't just think it was going to be that easy, right? We are adding functionality here, so it's not just about ditching our exit status indicator. Think about it; we need to add the current working directory to that right-hand prompt. Your first guess might be along the lines of the following command:

# this won't work! RPS1=%(?..(%?%)) %~

This is almost perfect, save for the fact that it won't work straightaway.

% source .zshrc > job not found: ~

Bummer! However, the slight detail that's missing is the usage of double quotes. That's right, we can sneak those spaces through the shell's string processing and come out with no errors just by using double quotes, as follows:

(36)

Chapter 1

[ 25 ]

This will tell the prompt function to take the RPS1 variable as it is and to not worry about parsing multiple parameters.

And, that's it. You have your own version of the prompt on your brand-new installation of zsh. Although, you might be wondering what's the deal with the second prompt that we left there. I'll leave it for you to decide its fate, as I really like the current old-school > indicator.

Before we are done with this chapter however, I'd like to point you towards the PROMPT THEMES section in the zshcontrib(1) manpage. Go ahead and type man zshcontrib on the terminal emulator of your choice for more detailed information when creating your own prompt themes.

Summary

In this chapter, we took a head-first dive into zsh by learning the essentials regarding its features and replacing your previous login shell. We even went that extra mile and added a touch of homemade goodness by customizing the prompt with the various escape sequences and configuration options available. Just because my memory is really awful, here's a list of what's been covered so far:

• We learned how to configure and set up zsh, so we could ditch your current shell and replace it with your brand-new installation of zsh

• We met the startup files, and now we have a clear understanding of what goes on behind the curtains moments before your terminal emulator window pops up on screen

• We got acquainted with the shell prompt, and discovered that zsh offers much more than meets the eye

• We went one step further and customized the prompt after learning about escape sequences and conditional expressions

(37)
(38)

Alias and History

In this chapter, we'll expand on the basics of zsh while focusing on aliases, one of the most time-saving features available. We'll take a closer look at how aliases work and learn to replace long, boring commands with our own short versions and automate the whole process within the startup files. We'll then move on to brace expansion, in order to avoid typing extra keystrokes whenever we can. Instead of typing the same things over again, we'll learn how to work with zsh's history and history expansion mechanisms and incorporate these new features into our workflow.

Working with aliases

An alias is an alternative way of saying the same thing. Think of it as a nickname for your commands. Though, unlike the embarrassing nicknames that you might get after a party, the alias mechanism provided by your shell is a handy shortcut to a series of commands and options under a friendlier name. The whole point of an alias is to do more and, preferably, type less.

I bet I got your attention with that last "type less" part. Allow me to explain:

The ls command lists a directory's contents. A quick look at its manpage (man ls) tells us that there are quite a few options there:

ls -a # lists all files, even those hidden that start with a dot ls -l # shows more information for each file, like size and permissions

Using aliases we can go ahead and do something like the following:

(39)

Alias and History

[ 28 ]

No spaces are allowed around the equals (=) sign. If the right-hand side of the assignment (that is, the part that comes after the equals) contains spaces or tabs, then make sure you use quotation marks around it as follows:

% alias talk='echo "quack!"' % talk

> quack!

Now guess what happens if you type la? Go ahead and try it. The shell reads your alias—la in this particular case—and expands it. The whole process is similar to looking up the meaning of a word in the dictionary. Although here, once it's been found, the meaning is executed.

We can do basically the same for the -l option:

% alias ll='ls -l'

Or even mix and match as shown in the following line:

% alias lla='ls -laF'

That last snippet uses both the l and a flags together with F, meaning it behaves just the same as the –la switch, with the added option to format the output so as to easily tell files and folders apart.

Aliases apply only to interactive shells. Your shell will disable all of your existing aliases if it's being run in the non-interactive mode. Keep this in mind when creating your scripts.

You have two ways of declaring an alias. The first one is straight from the command line, as we have been doing so far. This nets you an alias which you can use instantly; the downside is that changes are only present temporarily for the duration of your current session. Close your terminal emulator or log out of the system and it goes the way of the dodo. The basic syntax for declaring an alias is as follows:

alias [shortname]=<longname or command(s)>

(40)

Chapter 2

[ 29 ]

Enter the startup files; if you recall from the previous chapter, startup files are read every time the shell starts, and its configuration is loaded for the current session. Kind of what the doctor recommended.

Let's open up your .zshrc then, and add the aliases we've been working on so far:

# put this on your .zshrc alias la='ls -aF'

alias ll='ls -lF' alias lla='ls -laF'

Save your changes, source (or use its alias, the dot (.)) your file, and aliases will be set for you to use on every future session of the shell. Despite their different behavior, both the ways of alias declaration sport the same syntax.

Quoting characters

Any given character can be quoted by adding a \ character in front of it. This is particularly useful when dealing with "special characters" which have an additional meaning, such as $, and even an actual \ character. Take, for example, the following echo sentence:

# this is wrong!

% echo 'that's a quoted sentence for you' quote>

The shell prompt indicates it's waiting for a quote character to be (properly) closed. The problem here is that we did not properly escape the apostrophe on "that's":

% echo 'that\'s a quoted sentence for you' > that's a quoted sentence for you

That's all nice and working, but what happens when we have a great number of escaping to do?

% echo 'Escaping single quotes like this \' with backslashes \\ is really tedious'

> Escaping single quotes like this ' with backslashes \ is really tedious

Luckily, zsh provides the RCQUOTES option as a workaround, which allows you to use double single quotes ('') for escaping:

% setopt rcquotes

(41)

Alias and History

[ 30 ]

What about double quotes then? Well, these are truly special and out of the bunch, as they allow you to perform parameter and command substitution as we'll see in no time. What you have to remember when using double quotes is that either ", \, $, and ` characters need to be escaped with a backslash.

Let's give double quotes a try:

% echo "'echo \"\$HOME\"' will print out '$HOME'" > 'echo "$HOME"' will print out '/Users/gfestari'

In the preceding example, the $HOME environment variable gets replaced by the actual value (/Users/gfestari) when the $ character is not quoted.

You can also use backquote within double quotes for executing programs:

% echo "zshenv is located at: `locate zshenv`" > zshenv is located at: /etc/zshenv

The shell will first execute locate zshenv as if it were any other command, and substitute its output within the parameters being passed to echo.

As you can see, you can work around single quotes' limitations for most day-to-day usage, and turn to double quotes, escape sequences, and parameter expansions whenever you have a particular need for doing so.

Single and double quoting aliases

Single quotes (') are required when using spaces on your alias assignments; nevertheless, it's generally advisable to use them regardless of the spaces on your right-hand side. Granted, this is a "just to be safe" approach, but trust me when I say it will save you from a couple of avoidable headaches when declaring your aliases.

On the other hand, if you wish to use things such as environment variables or parameter substitution within your assignment expression (think of the prompt escape sequences we saw in the previous chapter), double quotes (") are required instead. Imagine you wish to output the current user's name with an alias. As we saw earlier, the direct way of accessing it is via the environment variable $USERNAME. The first thing that comes to mind then is to use the following alias:

# This is wrong!

(42)

Chapter 2

[ 31 ]

Unfortunately, this won't work with single quotes. The correct way of doing this is with double quotation marks as follows:

% alias saymyname="echo $USERNAME" % saymyname

> gfestari

Complex expressions with variables generally need to be quoted, we use single quotation marks for that. If your alias requires variables to be expanded before the alias is used, go with double quotes.

As you can see, the alias mechanism is indeed a nifty powerful feature. If used properly, it even allows you to reshape a command's meaning:

% alias ls='ls --color=auto'

Or its equivalent on OS X:

% alias ls='ls –G'

You can define aliases from another alias. Following the preceding

example, if you do the following:

alias ls='ls --color=auto' alias la='ls -a'

The la alias will behave just as if you typed ls --color=auto –a, there's no need to type --color=auto again on your definition.

This alias alters the behavior of ls by calling it with the color flag every time you type it, instead of using its more vanilla version. While this comes in handy for this particular scenario, it can be really dangerous for commands such as rm if not used with caution.

For example, imagine what would happen if you aliased a force removal of files to rm:

# Be careful when doing things like this! alias rm='rm -f'

(43)

Alias and History

[ 32 ]

So, what if you don't know whether you are bypassing any of the aliases' current set for your session? Well, there's a command for that. Typing alias will list all the aliases for the current session:

% alias > la='ls -aF' ll='ls -lF' lla='ls -laF'

saymyname="echo $USERNAME"

You can also get the information for a particular alias simply by specifying its name, as follows:

% alias la > la='ls -aF'

And you can disable, albeit temporarily, any existing alias by typing:

% unalias <aliasname>

Simply replace aliasname with the name of the alias you want to turn off. This comes in really handy on those occasions when you're using a particularly strict program whose options, or even command-line syntax, is overridden by an alias.

There are a few ways by which you can prevent the shell from executing an alias that is called just as another command. Single-quoted commands and commands prepended with a backslash (\) as well as those typed as relative or absolute paths are not treated as aliases by the shell.

For example, you could use either of the following if you wish to avoid a call to an alias:

% 'ls' % \ls

or even:

% /usr/bin/ls

Zsh also has command that will execute any argument as an external command instead of as a function or built in. Thus, you can also use it to avoid aliases. That would leave us with the following for the preceding example:

% command ls

(44)

Chapter 2

[ 33 ]

As with many other things we'll be discovering throughout this book, an alias is not a golden hammer and as such, you shouldn't be aliasing willy-nilly throughout your terminal sessions. Here are a few simple considerations to keep in mind before you embark into your less-typing adventure with your pack o'aliases:

• Is my alias easier to remember? echo -n is way simpler than aliasing something like echodontprinttrail. Keep it simple, don't use aliases for the sake of it. The "Future You" will be really thankful two months from now.

• Is my alias easier to type? An awkward alias is an awful alias. Using alias grepcola='grep --color=auto' instead of a simpler grep, really? Remember: clear, concise names are awesome, but something you can't remember for the life of ping is not cool.

• Is my alias overriding some behavior just for the sake of it? Think of the previous rm -f example. Most of the time we would like to stay away from something like that; however, prompting the user each time seems like a sensible feature to add to our toolbox. Aliasing rm='rm -i' so the shell requires confirmation before deleting something seems a bit... nicer. Be careful with these kinds of tricks though, as relying too much on such an alias could lead to a false sense of security. That is, imagine what would happen if you get used to rm constantly waiting for confirmation and eventually use it recklessly on a different environment?

Global aliases

If you enjoyed the simplicity aliases brought to the table, then global aliases are the icing on the cake. As the name implies, global aliases are, well, aliases that can be used anywhere, allowing you to treat filters or certain commands as a simple suffix.

Let's see some examples:

alias -g L='|less'

Pay particular attention to the -g option, as in a global alias.

Now you can append the less pager to any command's output, just by adding the L suffix:

% ls -la /etc L

Another option that is frequently spotted in the wild is redirecting standard error (stderr) and standard output (stdout) to /dev/null, so any given command can run silently:

(45)

Alias and History

[ 34 ]

This will allow you to call things such as command NUL without the need to pollute your current terminal window with thousands of log lines and messages.

Just for the sake of clarity, never mind sticking to standards, it's advisable for you to try and define your global aliases just like your global variables, all in caps.

Hashes

You can use a hash to give a particular directory an alias. This is particularly convenient for your workspace:

% echo $GOPATH

> /Users/gfestari/workspace/go

I don't want to type /Users/gfestari/workspace/go each time I want to reach the src folder in my $GOPATH directory. So how about putting hash to a good use?

% hash -d gosrc=$HOME/go/src

And now we can get there as quick as typing cd ~gosrc (pay attention to the leading ~ character).

Here's another example, this time using the /var/www directory:

% hash -d www=/var/www % cd ~www

/var/www

You can go ahead and hash your most frequently visited directories. Just remember to add the required entries to your .zshrc, so you don't have to type the same thing over and over again.

For bonus points, set the AUTO_CD option, so you only need to input the directory's name whenever you want to change the working directories:

% setopt autocd % ~www

> /var/www

(46)

Chapter 2

[ 35 ]

Putting it all together

Before we move on to the next topic, here's a couple of things to try with our newly found aliases.

Raise your hand if you found yourself typing cd .. more than a few times on a terminal session. I know, I feel your pain. How about making it simpler?

We could try the following instead:

% alias ..='cd ..'

Now it's just a matter of typing . to move your current working directory up one level. Not bad, uh? We can take it a bit further:

alias ...='cd ../..' alias ....='cd ../../..'

I'd argue that going more levels in for directory changing is pushing things a bit too far, but feel free to extend your aliases as you see fit.

What about creating directories? I bet that, like myself, more than once you saw the following:

% mkdir dir1/dir2

> mkdir: dir1: no such file or directory

This happens because dir1 doesn't exist. So what we do is—you guessed it—create an alias that allows us to automatically create the parent directory and also, be more verbose (as in, "list directories as they are created") about the output:

alias mkdir='mkdir -pv'

Now try to issue mkdir dir1/dir2 and see what happens. You can also apply the same switch to commands such as cp and mv, just remember to quote your assignments!

You can use the COMPLETE_ALIASES option in your startup

files in order to force the shell to treat aliases as a distinct

(47)

Alias and History

[ 36 ]

Expansion

The shell allows you to perform different types of manipulations right before

executing a line. In the following section we'll learn how to take advantage of each of the different forms of expansion and substitution available in zsh.

Parameter expansion

Parameter expansion allows you to replace known variables in between the assignments of the command line. Simply put, parameter substitution is the mechanism by which the shell can change the following:

% foo=Hello

It will be changed to the following:

% echo "${foo}, world!" > Hello, world!

Notice how the variable foo we declared in the previous line is replaced inside the arguments of echo with its actual value. You should be paying special attention to that peculiar ${} construction. What happens is that when zsh reads the ${foo} construction, it immediately knows it has to replace what's in it with whatever value it holds.

The astute reader might also have taken notice of the double quotes that surround the echo arguments. It's important to remember that just like aliases and prompt sequences, parameter substitution will work for arguments passed between double quotes, just like every other variable out there.

Command substitution

Like parameter expansion, command substitution allows the shell to execute a command call and replace its output within a specially formed syntax. Command substitution usually takes the form of `command`, a program name wrapped around back quotes.

(48)

Chapter 2

[ 37 ]

In the wild, command substitution is frequently used to find out the full path to a command:

% print $(which zsh) /usr/local/bin/zsh

Or, to make it more portable:

% print `which zsh` /usr/local/bin/zsh

Arithmetic expansion

Don't let the name discourage you; just like parameter substitution, arithmetic expansion is yet another form of substitution to help us sail swiftly across the command line. As its name implies, you can expand your input into a series of elements that will otherwise require you to type a lot.

Let's try it:

% echo $(( 5 + 4 )) > 9

We started with some rather simple arithmetic expression (I know, I know; Math). But fret not, what just happened can be easily explained. We already know echo prints information into the standard output, so there are no mysteries there. What follows it is just an arithmetic expression using the $(( )) construct. Notice that, unlike parameter substitution, this kind of arithmetic substitution requires an extra set of parentheses. This is our way of letting zsh know that it needs to work with numbers, and that's why our 5 + 4 is treated as such.

The same rules apply to the following:

% echo $(( 5 + 4 * 3 )) > 17

Which leads us to realize we need more parentheses for operator precedence:

% echo $(( (5 + 4) * 3 )) > 27

(49)

Alias and History

[ 38 ]

Interestingly, we can invite parameter substitution to this party too. Looks like variables can also be substituted inside arithmetic expressions:

% num=5+4

% echo $(( num * 3 )) > 27

In the preceding snippet, we declare a variable to hold our 5 + 4 expression; this makes num a container that, when asked what's up, will yell out our 5 + 4 expression. An easy way to check this is:

% echo ${num} > 5+4

Note however, that by using num in the expression we did not require an extra set of parentheses in order to set operator precedence. This is because our num variable gets replaced on the following line with its value, which leaves us with an expression equivalent to (5 + 4) * 3. Expressions get evaluated before they are replaced, otherwise the result of the preceding call would have been 17.

Let's kick it up a notch with another handy arithmetic substitution:

% num=5+

% echo $(( $num 4 )) > 9

On this opportunity, we are leaving the num expression as something that resembles "add whatever follows to it". This is why when it is evaluated on the next line, it gets replaced for what you'd expect, in this case 5 +. See that $ right before the num variable? Remember parameter substitution from the beginning of this section? That's what's going on here. Without that $num there, zsh simply does not know how to deal with the num assignment:

# This is horribly wrong! % num=5+

% echo $(( num 4 ))

> zsh: bad math expression: operator expected at `4 '

Remember, if you wish to substitute a parameter, use $:

% echo $(( $num 4 ))

(50)

Chapter 2

[ 39 ]

Brace expansion

Another useful type of expansion is known as brace expansion. As the name implies, its syntax has to do with the use of curly braces ({})—I suppose "curly brace expansion" was a bit too verbose when they were picking a name for it. Brace expansion allows you to declare an array of entries as follows:

% echo picture.jp{eg,g} > picture.jpeg picture.jpg

What happens then is that the {eg,g} construct gets expanded into an array containing the elements eg and g. The shell then loops through those elements, passing two arguments to the echo command, which basically has the same meaning as typing the following:

% echo picture.jpeg % echo picture.jpg

But you saved yourself from quite a few keystrokes and the accompanying boredom. Let's try another example:

% touch log_00{1,2,3}.txt % ls

> log_001.txt log_002.txt log_003.txt

This time we are creating simple logfiles with the pattern log_00<num>.txt. The shell expands the {1,2,3} element into the elements 1, 2, and 3, and then calls the touch command three times:

% touch log_001.txt % touch log_002.txt % touch log_003.txt

In case you didn't notice, we use commas (,) in order to declare each of the elements inside curly braces. Now, you might be thinking "what happens when we use a longer array?" Here's when it gets even more interesting; declare a range of values:

% touch log_{007..011}.nfo % ls | grep .nfo

(51)

Alias and History

[ 40 ]

It's worth noting a couple of things going on with the preceding example. I took the liberty to format the output of the list. But that (…) implies files 007 to 011 do exist. Firstly, we are now using brace expansion to extend a range, this time from nine up to eleven. The next thing that's also worth mentioning is that zsh is smart enough to notice the leading zeros and use it as a padding for the other values instead of replacing them with, say, vanilla integers. That is why you see the sequence starting with log_007.nfo and ending with log_011.nfo.

On the second line, we use a pipe symbol (|) to link or redirect output between different commands on your shell. This way we are listing the contents of the file, and redirecting the output into the utility grep, so we can filter said output by the .nfo extension.

Arrays can get even more interesting when we sparkle a bit more math in them:

% foo=(A B C) % bar=(1 2 3) % echo $^foo-$^bar

> A-1 A-2 A-3 B-1 B-2 B-3 C-1 C-2 C-3

In the preceding snippet, we declare two arrays, one containing the elements A, B, and C, and the other with the elements 1, 2, and 3. The call to echo then passes the argument ${^foo}-${^bar}. Notice the ^ operator (curly braces were implicit on the previous call, so I added them here for the sake of clarity). Again, we are telling zsh to expand the variables that come after the $ character, only this time we get a Cartesian product instead of, say, A B C-1 2 3. This is because the ^ operator serves as the array expansion expression. So as far as zsh is concerned, we're using each element of the array independently.

For a more detailed description of how array expansion and the ^ operator works, visit man zshoptions (particularly, the RC_EXPAND_PARAM section) and man zshexpn.

As with other sequences, some characters are considered "special" and need to be escaped. Commas and single quotes need to be escaped with a backslash:

% echo \'{\,,\'}\'' needs to be escaped'

Gambar

figure out the location of our existing zsh installation. The job of  consists of shouting out loud the location of any program file in the user's $PATH environment variable

Referensi

Dokumen terkait

Pendaftaran dan download seperti jadwal pada SPSE Kabupaten Pulang Pisau dan lebih jelasnya dapat dilihat di website: http://lpse.pulangpisaukab.go.id. Demikian disampaikan

menunggu murid murid yang lain sambil melantunkan bola diikuti dengan murid kedua

instrumen final untuk mengukur konflik pekerjaan keluarga (work family. conflict)..

Digunakan dalam pelaksanaan pekerjaan yang terkait dengan melaksanakan evaluasi pelaksanaan diklat lingkungan hidup pada SKPD yang membidangi lingkungan hidup di

Masih perlu adanya penambahan jumlah pustakawan yang khusus bekerja di Perpustakaan Umum dan di ruang layanan referensi yang bertujuan untuk membimbing dan membina staff pegawai

[r]

Unit Layanan Pengadaan Kota Banjarbaru mengundang penyedia Pengadaan Barang/Jasa untuk mengikuti Pelelangan Umum pada Pemerintah Kota Banjarbaru yang dibiayai dengan Dana

- Land Use Change and Climate Change in Citarum River - Sea Level Rise in Indramayu and Subang... Banjir Jakarta