Five tips to make your bash life easier

A number of tricks and shortcuts can save you time and keystrokes when you're using bash to knock out various chores. Here are five handy tips to get you started.

Bash is that tool in *NIX-land that you're really only thankful for when you need it. Of course, most people don't realize it, but that's most of the time. So many things in *NIX-land depend upon bash. The command line is the biggie. But you wouldn't be pulling off fantastic shell scripting if it weren't for bash. So I thought it apt (pun intended) to offer these tips to make your bash life all the easier.

1: Use aliases

An alias is a shortcut for a command that's challenging to type (or to remember). Instead of typing sudo apt-get update and sudo apt-get upgrade, you could add the alias alias update="sudo apt-get update ; apt-get upgrade" to your ~/.bashrc file. Then, you'd just have to issue the command update to do the work. Aliases are simple ways to keep the typing in the command line down to a minimum, as well as saving you the trouble of remembering tricky commands.

2: Use bash history

This one is so fundamental that people often forget it's even there. Bash retains a history of all commands issued. Typically, bash will retain the last commands run (how many bash retains will depend upon your distribution). That's a lot of commands to remember. But how do you see them? You can issue the command history, which will list out all of the commands used (currently mine lists out 596 commands). What you might not know is that you can use the up and down arrows to scroll through the history listing. So instead of retyping that command you recently used, just hit the up arrow until you find the command. And unlike Windows, bash will retain this history even after you have logged out and logged back in.

3: Pipe output

One of the bash tricks I use daily is piping output of one command through another. This means that the output of one command will be used by the next command. The simplest example of this is using the dmesg command. When you issue dmesg, the output flies by so quickly you can't see it. Instead, pipe the output to the less command so you can see the contents of dmesg one page at a time. This is done like so: dmesg | less. The "|" character tells bash to pipe the output of the first command through the second command.

4: Join commands

Instead of running ./configure, make, and make install separately (having to wait for the output of one command to finish before issuing the next), you can do it all from one command using the ";" character. The command will look like this:

./configure ; make ; make install

Of course, since running make install most often requires root privileges, you'll have to run all three with sudo or after issuing the su command.

5: Outfox those spaces

This one will often bite you in the keister. We all know that Windows (and Windows users) are, for some strange reason, in love with using spaces in file/folder names. Why this is, I have NO IDEA. Linux (and all UNIX-based OSes) do not like spaces in file/folder names. But that's okay. You can get around this by surrounding the full file/folder name with "". So if you have to delete My Folder, you could do so with the command:

rm -rf "My Folder"

You could also use the "\" character instead, like so:

rm -rf My\ Folder

Notice the placement of the space in the My Folder name. That is important.

Other tips?

These five easy tips should make your bash life a wee bit easier. If you've dealt with any flavor of UNIX, you know that there are tons of such tips out there. I have found, however, that these five are the best ones to learn right away. They will save you a lot of time and prevent a lot of headaches. Do you have a handy bash tip to share with your fellow TechRepublic readers?

Check out Five Tips... the newsletter

Get a concise roundup of solutions and techniques that will make your IT job go more smoothly. TechRepublic's Five Tips newsletter, delivered every Tuesday, gives you instant access to the information you need. Automatically sign up today.

About Jack Wallen

Jack Wallen is an award-winning writer for TechRepublic and Linux.com. He’s an avid promoter of open source and the voice of The Android Expert. For more news about Jack Wallen, visit his website getjackd.net.

Full Bio

Jack Wallen is an award-winning writer for TechRepublic and Linux.com. He’s an avid promoter of open source and the voice of The Android Expert. For more news about Jack Wallen, visit his website getjackd.net.

if you are not typing the command, some will forget it, or at least the way it has to be laid out.
Go to someone else's system and your little alias is not there, now what?
This is the same reason I was always a Vi advocate, I know it will be on EVERY system I sit down at.

As Jaqui says the using the join command for compiles is doomed to ruin a perfectly good day.
./configure, resolves libraries and dependencies
make, compiles the output from a configure
make install, installs the output from a make.
Using the join starts all 3 processes before any one of the processes complete. Older outputs from ./configure and make, would be passed to the processing make, and make install instead of the current ./configure.
./configure can fail with errors, without input make, and make install will fail.
More correct compile that checks return status:
./configure && make && make install
A more appropriate use of join would be start non-dependent processes, ie,
/usr/bin/thunderbird; /usr/bin/firefox; df -h

Great tips, but statements like this from otherwise clearly intelligent people are annoying. Really? You have NO IDEA why my mother-in-law would want to store photos in a folder named "Pictures of my grandchildren" instead of "pictures_of_my_grandchildren" or "picturesofmygrandchildren" or "picturesOfMyGrandchildren"? An OS with a command line AND the ability to handle spaces in filenames was one of the reasons I switched to NT back in the day. Keep the tips coming, but take a step out of *nix land occasionally.

I like doing multiple commands at once but "&&" is the way to go rather than ";" for my needs.
./configure ; make ; make install
if ./configure fails, make will still try to run. If make fails, make install will still try to run. This is especially not good when commands rely on the results of the preceding command. What happens if you don't want to make or make install if ./configure fails while your fetching coffee?
&& = run something else only if something was successful.
./configure && make && make install
If ./configure returned no errors then try make. If make returned no errors then try make install. If ./configure or Make returned errors, they'll be waiting on your screen when you get back from fetching coffee.
& = run something in background and give me back the command line.
rm -rf /var/lib/archive/old/* &
I go do something else or continue with cli work while files are deleted in the background.

quote "And unlike Windows, bash will retain this history even after you have logged out and logged back in."
Jack, don't know where you get this idea. Unless you haven't used Windows since about 1992 or so with Win3X, because on almost all the systems I've used with 9X and up, the run command will list all the previous commands I've used up to however many I want, unless I configure it NOT to keep them.
Why would you want to keep 500 plus commands history anyhow?

Vector Linux went emacs and didn't include Vi(m) when I last looked at it.
I have noticed that more distros are starting to add nano as automatically installed cli editor. maybe my comments about learning curve for Vi(m) and emacs making them bad options for default text editor for newb friendly helped. ;)

*nix systems can manage with spaces in the file name and make use of more characters than ntfs file names (for better and worse). That still doesn't make the space character a good choice when naming files and directories even in Windows. If you want a nice long description; put it in the metadata that any viewer will display or the file explorer preview can show.

Hitting the tab key part with through a file or folder name is a wonderful habit to develop and quickly becomes automatic.
Thankfully, Windows has some form of the same though Bash tab completion feels far more elegant than CMD.exe. Hit tab a second time for a list of potential matches versus hitting tab repeatedly until the desired match pops up on the command line.

Not really a bashism but useful. The -p flag on mkdir.
I don't know how often I forget about it but it is a lot.
Instead of
mkdir new_project
mkdir new_project/docs
just use:
mkdir -p newproject/docs
The end folder and all the ones in between that don't exist get created. Quite nice if you are doing something like a rolling backup or something. If the folder for the month is already there then the day folder gets created, but if the month hasn't been backed up yet then folder and subfolder get created all in one go.

Please enlighten me on the command to recall commands from a previous session.
And why would you want 500+ commands in your history? cd is a command, pwd is a command, su is command. You will see your command history full of commands like this. The one you are looking for may be way down in the list. Luckily UNIX/Linux also has quick and powerful search methods and command line editing (if you like vi).

Long history is useful for remember unique and/or long commandline strings or obscure examples of using the command, especially true for bash, csh, etc.
For example, saving a couple of quick commandline SQL queries, or finding and deleting old files.

The alias tip was the only one new to me and of course there wasn't enough detail to use it...
I tried creating a .bash_aliases file but rather than acting as an alias it tried to run them when I opened a terminal window.
A link to a good bash alias document would be great
Thanks!
-PaulK

Wizard, he's talking about the Windows command prompt, not the Run command. Bash (and sometimes Windows/DOS commands) can be much more complex than a single word, and if you have typed a long one in Bash yesterday or a week ago, it's nice to be able to call it up quickly without having to work through the options again.

... are doomed to unnecessarily repeat it.
You HAVE to mention Ctrl-R letting you search backward through bash history for a command, iteratively, letter by letter as you type, then hitting enter to run it, or arrowing to edit it before running.
And !500 running the 500th command in your history, is sometimes useful.

every picture on "grandma's" pc are all dumped in "My Pictures", either in one huge directory OR the only separator being the date or random numbers the camera/scanner decide to save them in.
Grandma doesn't know how to make a directory structure.

Cryptic or smashed together file names IMO are just another reason **NIX has such a problem being main stream. I'm old enough to remember why we started no spaces and short cryptic names in the first place. No memory or storage space. We have long since left the world of 40meg HD's and 640k of memory. With $100 1tb drives and 8gigs of memory who cares.

'screen' is more robust than using 'nohup', as it allows you to spin off the process into a virtualized terminal session that will persist when you disconnect, and allow you to reconnect later -- which is how you can "check back later" as Neon puts it.
It also multiplexes multiple instances of such sessions.
I use it daily to open a session in a private account on a group machine in our lab, launch an app, then close the terminal session -- which takes away terminal access to the private account, but still allows the app to run -- with access to certain files in the private account.

When using tab completion if there's ambiguity about the filename, Bash requires you to specify exactly which one you want. Windows just takes a wild stab at it and gives you one of the files - usually the wrong one. :p

For years I've used ln -s then only recently discover cp -s. Copy is cp thingy newthingy, ln is ln thinging alias. I'm so used to copy's "original target" order that I always have to stop and think about link's "target alias" order. OR, just use cp -s original alias. :D
mkdir -p is very handy for bash scripting installs.
find -exec is also becoming very handy for my needs (since we're going outside of Bash world here).

in your history is easy:
Press Ctrl-R and begin typing the first few characters of the command you wish to recall.
Once it's sufficiently un-ambiguous, you can then repeatedly press Ctrl-R to step backwards through all other matches in your history file.
The 'cd' and 'su' and such in your history file is good to have: You'll want to see it all for forensic purposes. Ctrl-R weeds them out when you don't.

manually each time you need one, simply type:
alias shortCommand='Long Command With Options and Arguments'
To have the aliases automatically created, you need to add them to a file. .bash_aliases is the default for many distros. Create a file that only contains the alias you need, for example:
alias ll='ls -ll'
alias la='ls -la'
alias lla='ls -lla'
etc.
Then include a line in your ~/.profile file to execute the file (see .env example below). Since I work with multiple UNIX systems, I created a new file called .env in which I put my personal settings. It's unique to me and it allows me to execute a script I have to copy the file to all of my UNIX servers to keep them in sync. I think add the following line to my .profile file:
. .env
Both periods are important! If I have to or want to add a new alias or make a change, I do it once and execute my script to copy the file to the other servers.

man alias
this will give you the list of built-in commands for bash.
the entry for alias reads:
alias [-p] [name[=value] ...]
Alias with no arguments or with the -p option prints the list of aliases in the form alias name=value on stan‐
dard output. When arguments are supplied, an alias is defined for each name whose value is given. A trailing
space in value causes the next word to be checked for alias substitution when the alias is expanded. For each
name in the argument list for which no value is supplied, the name and value of the alias is printed. Alias
returns true unless a name is given for which no alias has been defined.

and add the arguments you need to it, and
it gets stored in the history. As I said,
Jack aparently hasn't used Windows in a long
time. I use BASH as well. Almost all of
the points he mentioned have been available
to CLIs for 25 years (of various OSes).

True, if she renames a file, she'll probably use a space character unless Grandma worked in the early IT field.
In this case, we're talking about tips for working with Bash so GUI and non-Bash platforms are kind of outside scope.
It's such a habit for me, I actually had to go back and think about why it seems so wrong. I use spaces all through my Windows filenames where data is only ever going to be accessed through Windows. Anything cross platform or potentially accessed though Bash gets camel-case dot separated names.
I ran into another example last night actually; "-". In the Bash world "-" usually denotes a command option/switch for example "ls -a" or "dir /a" in the Windows world. Because bash puts power in the user's hands, I ended up with some files named "-p1-65535" (anyone guess the command line I messed up?).
Now, in a command line environment, try just deleting the three "-p1-65535.*" files.
rm "-p1-65535*"
rm -p1-65535*
rm \-p1-65535
All returned a "argument not recognized" error due to mistaking "-p" or "-6" for part of the command rather than part of a file name.
rm \-p1\-65535 (didn't try this one.. may have worked)
Rather than bang away at the command line, it was quick to open a GUI file browser and go select/delete the three files. Point being that if we're making Bash life easier " " or "-" are less than ideal file or directory name characters. ;)

True enough, but if Grandma SHOULD happen to name a file, she's likely to use spaces and special characters, not having been trained in the fine points of file naming.
As an aside, I've seen essentially empty files with filenames that are whole paragraphs. The user put all the data in the filenames. :-)

because it causes difficulty for others to parse and understand what we wish to convey.
Similarly, *adding* spaces to file (and directory) names on a computer does the same thing: It makes it difficult to parse and understand what is meant.
Ergo, use camel-case and/or add spaces and hyphens to separate "words" in a filename -- and then it becomes obvious to machine and human what's a token and what is not.
Even "Aunt Millie" can handle that... :^)

Spaces in filenames is one of those things that bugs me depending on the OS.
With windows, I make use of spaces for short one to five variable file names. It's primarily interacted with through the GUI and the CLI expects spaces in file names. I discourage file names becoming paragraphs rather than short descriptions. Windows does complain about special characters it doesn't want in file names. For example, you can't have "\" as part of a file name. It's not desirable but with GUI primary interaction, I'll adapt in exchange for the added power of cli.
With bash type environments, space separates command and arguments/options.
commandbinary --longoptions -options argument1 argument2
commandbinary = the program "ls, cmd.exe"
" " = seporating space preceding new part of command
-- = indicates following letters are all one argument; eg. --script-updatedb
" " = separating space
- + single dash indicates following letters are read as individual options; eg. -lha same as -l -h -a
" " = separating space
argument1 = whatever applicable; eg. the source file in "copy sourcefile.txt destination"
It has an intended special use on the command line. It's the nothing separating somethings. It's the default null value for a character cell. It's like using an air-gap to support a second floor instead of building frame or pillars. It's like using "\" in a file name when that is already specific to separating directorynames and filename in a typed path.
But, bash gives power to the user by default. It allows the use of special characters where they shouldn't be used if the user so chooses. "\" says "treat the following character like a normal text character" so "file\ name.txt" is read as "file name.txt" not "file" and "name.txt". You can wrap every path/filename in quotes but this means always specifying the anomaly rather than defaulting to the norm just to support a bad habit.
It also slows things down when working on the command line and in scrypts. tabbing completes long file names and dashes, dots or underscores are easy to read across. Rationally short names and camel-case also works. With a well layed out clean directory structure you reduce the need for paragraph long filenames since the directory location should indicate most relevant information.
Granted, we are also talking more specific to working within Bash here. The good habit is simply too easy not to avoid the bad habit.

My personal issue is that they become messy quickly. I have to use a "\ " or wrap quotes around a filename that includes spaces even on Windows. I can tab my way through a camel-case or . separated word faster than space separated.
It leads to bad habits like:
This is my letter to aunty ethel about my favorite colour blue.txt
where your using a long text description for what should be a short text filename:
letters-aunty-ethel-colour-blue.txt
letters-aunty-ethel-sunday-flowers.txt
With a 255 character limited already partially consumed by "c:\documents and settings\niece-alice\My Docments\" long filenames lead to strange errors an inability to properly access files under Windows. I frequently run into issues caused simply because a twenty character filename is buried under several twenty character directories resulting in "file or path exceeds 255 character limit".
Ability to name files " " potentially hiding malicious intent from users that don't think to look for " ", " ." ". ". Because " " is a valid filename character on other platforms, Windows is reinforcing a dangerous habit.
In the end, it's his and/or his grandmother's machine to manage files how they like. My persute of cross platform good habits isn't going to affect them either way.

It's really the displaying potential options with Bash tab complete that gets me. I miss it with Windows displaying tab complete on the command line in alphabetical order. Three more tabs gets me down to that fourth option I actually wanted. Much slower than seeing the options and selecting a relevant letter before the next tab complete.
I'm glad Windows has some form of tab complete though along with recognizing && for chaining commands.

#ls.cmd
dir %1 %2 %3 %4 %5 %6
#rm.cmd
del %1 %2 %3 %4 %5 %6
#su.cmd
runas /u:administrator /c:"cmd"
(you'll want to look that last one up with a runas /? of course)
There is a nice set of binaries for windows that turns up from time to time including grep and some other utilities. If you really want to unix it up.
I figure, take the good habits from one and port them to the other. There is recognizable Windows user in my *nix home directory.

I got started in the CP/80 days, and cut my teeth on UNIX in college, so the CLI is second-nature to me...
I use it frequently in Linux, but not often in Windows -- and that's probably because of the limitations of what you can do with a CLI in Windows (which may be partly due to me not knowing the commands to do things).
With Linux, it's almost a necessary thing -- well, it IS necessary if you're doing any significant system admin tasks -- but there are still some things that I'll prefer using a GUI for (disk partitioning, copy-merging files) simply because the GUI limits my options...
Which means: It prevents me from fat-fingering a command or using the wrong (and perhaps disasterous) syntax for doing something. I prefer to have both, so that I can choose which tool is faster/better/safer to use. 'bash' really helps.

He was replying to the Windows comment at the post to which he replied.
Not that your post wasn't chock full of good information. :) I appreciate picking up on the various nuances and further facts, as I don't use a 'nix CLI super frequently.

jpmigue said, "Please enlighten me on the command to recall commands from a previous session. ... And why would you want 500+ commands in your history?"
So I replied to (only) that, not to the post that jpmigue was replying to. However, going way back to the top, he was probably referring to Windows (I read it as Linux, since we were discussing 'bash'), and he was also probably quoting about the '500 commands' part -- but not indicating he was quoting -- and it came across as asking a question, to which I replied.
Y'all note the use of *punctuation* in the above so as not to be so ambiguous. :^) Years of communicating to computers to get them to do our bidding should make most of us aware of the importance of syntax and symbols so as not to confuse... :^D
(I know, it's gone out of style in this "texting" world we're living in now... Oy.)

I create a ~/bin in the applicable user's account which limits it to being accessible and run only by the specific user. /root/bin is usually cront.something scripts wired into crontab (nice short path). Anything else root needs a script for makes sense to keep inside the builpack directory so it's a "./something" run. /home/user/bin is user specific things.
I guess I could do user specific aliases to these locations or add the locations into the path but but specifying the path or going to that directory doesn't slow me down enough.

if you are aliasing or linking commonly used existing commands, like for system admin type tasks, you would want the alias or link in the same folder as original, for the permissions.
you wouldn't want a regular user to be able to run mke2fs /dev/hda1 now. :D

The system gets /bin /lib.. The /usr gets /bin /lib.. I figure that works for my user accoutns that get user specific ~/bin ~/lib as needed. It's the old Dos user in me still doing .bat files. ~/lib for user specific tarball, svn or rsync installs. ~/bin for user specific executables (usually scripts pointing at ~/lib).
I really should make more use of aliases. Except for un-commenting root's coloured bash settings, I mostly use them for quick short term storage when repeating the same command several times. Adhoc simple scripting as it where.

I see where your issue lies.
you can't type ./bash_alias at the cli, bash will always want to execute the commands, not create the aliases. you can include the bash_alias file into the .bashrc or into the global /etc/bashrc
including them in one of the .bashrc files is the only way to have the aliases remade with every terminal opened / reboot.
What I do instead is actually create links with ln. those are permanent so only have to do it once.
the links do need to be made with root privs to have write access to /bin, /sbin, /usr/bin or /usr/sbin.
The failure of links is the "sudo apt-get update" functionality used in the alias example isn't available.

used@host:~$ man alias
No manual entry for alias
also what you copied from the man page didn't answer my question.
Like I said an alias tutorial or document would be very useful. If the man page solved my problem I wouldn't have asked.
Thanks but still didn't help...
-PaulK

The test with terminalA and terminalB open showed that the history is not shared between sessions. Closing the terminalA&B then opening terminalC showed that history does not move from closed old to fresh new session. Logout/login was done since it was the original test case.
Doskey was great in it's day. For me though, it was actually working with a Linux distro; I hit the up key in winNT by habit and discovered that it had the history automatically instead of needing doskey.

Neon, no need to log in and out to test cmd's
history. Just exit cmd and start it again.
And as proven, wizard, history is not retained in cmd once you close the window.
Using 4NT/TCC as a replacement we could get
the benefit of a history though one has
to make sure to save/reload the history
otherwise it acts the same as cmd (no retained history).
BTW, one of those things we forget about or
didn't even know in cmd.exe is use of F7 and
F9 to bring up a history list or go directly
to a history line.
DOSKEY stuff I guess. A command I never bothered to use even back in the DOS days.

I think your still missing the context. We're talking about the command history provided by cmd.exe at the command line prompt. This has nothing to do with the run dialog (Win+R).
(I needed an excuse to kick over the winXP vm.)
Logging in..
- Win+R = cmd [Enter]
- CMD.exe > Up Arrow returns nothing
- CMD.exe > "dir" returns directory/file listing
- CMD.exe > Up Arrow returns previous command "dir" which returns directory/file listing
Logging out..
Logging in..
- Win+R = cmd [Enter]
- CMD.exe > Up Arrow returns nothing
- CMD.exe > "dir" returns directory/file listing (to create a history)
- Win+R = cmd [Enter] (second terminal open)
- CMD.exe > Up Arrow returns nothing
When first logging in, no history exists within cmd.exe/command.com. Up arrow returns no previous commands.
After entering one or more commands, Up Arrow will return history for that session and terminal combination.
When opening a second cmd.exe terminal while the first remains open, Up Arrow in that second terminal does not return the first terminal session's history or it's own prior history since the up arrow is the first interaction with the new terminal session.
For comparison using Bash inside Konsole:
- bash $ Up Arrow returns "exit"
- bash $ Up Arrow returns "su"
- bash $ Up Arrow returns "exit"
- bash $ Up Arrow returns "ls -l"
- bash $ "ls thetest" returns No such file (run to create identifiable history)
second Bash inside Konsole:
- bash $ Up Arrow returns "exit"
- bash $ Up Arrow returns "su"
Close first Konsole, Close second Konsole, open third Bash inside Konsole:
- bash $ Up Arrow returns "ls thetest"
- bash $ Up Arrow returns "exit"
- bash $ Up Arrow returns "su"
Bash remembers my history from the last session and across logins.
Bash saves my history globally within my user account so opening a terminal after closing the previous will include the previous terminal's history.
Opening a second terminal will provide history excluding the first open terminal since terminal1 hasn't been closed to save it's history globally.
If I want to see what I've been up to I can "less ~/.bash_history". If Root wants to see what users have been up to; "less /home/user/.bash_history". Root could also script something quick and easy to dump user's .bash_history into a central file retaining the history even if users deleted there personal .bash_history file.
Also, if you keep clean machines including removing form field history between logins, that history in the Win+R pulldown is going to be pretty short.