Bash - Ubuntu: Questions and Answers (2014)

Ubuntu: Questions and Answers (2014)

Bash

Skip to questions, Wiki by user ændrük

Bash is a command processor, typically run in a text window, allowing the user to type commands which cause actions. Bash can also read commands from a file, called a script. Like all Unix shells, it supports filename wildcarding, piping, here documents, command substitution, variables and control structures for condition-testing and iteration. The keywords, syntax and other basic features of the language were all copied from sh. Other features, e.g., history, were copied from csh and ksh. Bash is a POSIX shell but with a number of extensions.

The name itself is an acronym, a pun and descriptive. As an acronym, it stands for Bourne-again shell, referring to its objective as a free replacement for the Bourne shell. As a pun, it expressed that objective in a phrase that sounds the same as born again, a term for spiritual rebirth. The name is also descriptive of what it did, bashing together the features of sh, csh and ksh. (Via Wikipedia.)


Questions

Q: Hide current working directory in terminal

Tags: bash (Next Q)

As a default, the terminal prompt shows something like:

user@system:/folder1/folder2/folder3/folder4$

the deeper you go into the filesystem, the less space is left for typing in commands. Can I change this to only show something like:

>

I mean, I can just type pwd to show where I am at. ;)

Tags: bash (Next Q)

User: theodor


Answer by oli

export PS1='\u@\h: '

That results in oli@bert: for my prompt.

If you really want something as minimalist as you ask for, try this:

export PS1='> '

You can attach that to the end of your ~/.bashrc file to have it persist between logins.

You can also get creative with some colours. Here's what I use on my servers:

export PS1='\[\033[0;35m\]\h\[\033[0;33m\] \w\[\033[00m\]: '

Giving (it's easier to see on a full black background):

My terminals

Glossary of acceptable characters in PS1


Answer by stefano-palazzo

Just to expand on Oli's answer (and so that I have a bookmark for those short-hand symbols):

The bash prompt (stefano@linux:~$) is only the first of a couple of prompts you might see,:

· PS1: The default promt you see when you open a shell

It's value is stored in an environment variable called PS1. To see its value, type

echo $PS1

This will give you something like

\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$

To change it, you can set a new value for the variable:

export PS1="\u > "

This will result in a prompt like this:

stefano >

· PS2: is your secondary prompt. This get's shown when a command is not finished. Type echo "asd and hit enter, the secondary prompt will let you enter more lines until you close the inverted commas.

· PS3 is the prompt used for select(2)

· PS4 is the prompt used for alt textstack traces (default: +)

To make the changes permanent, you append them to the end of .bash_profile (or .bashrc, see this question) in your home directory.

Here's a more or less complete list of shorthand that you can use when composing these:

· \a The 'bell' charakter

· \A 24h Time

· \d Date (e.g. Tue Dec 21)

· \e The 'escape' charakter

· \h Hostname (up to the first ".")

· \H Hostname

· \j No. of jobs currently running (ps)

· \l Current tty

· \n Line feed

· \t Time (hh:mm:ss)

· \T Time (hh:mm:ss, 12h format)

· \r Carriage return

· \s Shell (i.e. bash, zsh, ksh..)

· \u Username

· \v Bash version

· \V Full Bash release string

· \w Current working directory

· \W Last part of the current working directory

· \! Current index in history

· \# Command index

· \$ A "#" if you're root, else "$"

· \\ Literal Backslash

· \@ Time (12h format with am/pm)

You can of course insert any literal string, and any command:

export PS1="\u \$(pwd) > "

Where $(pwd) stands in place of "the output of" pwd.

· If the command substitution is escaped, as in \$(pwd), it's evaluated every time the prompt is displayed, otherwise, as in $(pwd), it's only evaluated once when bash is started.

If you want your prompt to feature colours, you can use bash's colour codes to do it. The code consists of three parts:

40;33;01

· The first part before the semicolon represents the text style.

o 00=none

o 01=bold

o 04=underscore

o 05=blink

o 07=reverse

o 08=concealed

· The second and third part are the colour and the background color:

o 30=black

o 31=red

o 32=green

o 33=yellow

o 34=blue

o 35=magenta

o 36=cyan

o 37=white

Each part can be omitted, assuming starting on the left. i.e. "1" means bold, "1;31" means bold and red. And you would get your terminal to print in colour by escaping the instruction with \33[ and ending it with an m. 33, or 1B in hexadecimal, is the ascii sign "ESCAPE" (a special character in the ascii character set). Example:

"\33[1;31mHello World\33[m"

Prints "Hello World" in bright red.


Tags: bash (Next Q)


Q: How do I create a permanent Bash alias?

Tags: bash (Next Q)

I would like to create an alias to rm command in order to have a confirmation message after executing this command. So I am creating an alias like this alias rm='rm -i'. But as far as I know this is a temporary alias and it lives until you close the terminal.

As it is explained here to save alias permanently I need to execute ~/.bash_aliases or ~/.bashrc commands in terminal and add my alias there. But when I execute ~/.bashrc I get following error message :

bash: /home/bakhtiyor/.bashrc: Permission denied

When I run ~/.bash_aliases I get another error message like this:

bash: /home/bakhtiyor/.bash_aliases: File or directory doesn't exist.

What is the actual problem and how can I solve it?

Tags: bash (Next Q)

User: bakhtiyor


Answer by karthick87

To create an alias permanently add the alias to your .bashrc file

gedit ~/.bashrc

And then add your alias at the bottom.

alt text

Now execute . ~/.bashrc in your terminal (there should be a gap between the . and ~/.bashrc.

Now you can check your alias.

alt text


Answer by aneeshep

There are lot of ways to create alias . The most used ways are :

1) . Add aliases directly in your ~/.bashrc file

For example. append these line to ~/.bashrc file

alias ll='ls -l'

alias rm='rm -i'

Next time when you type rm the rm -i command will be executed.

2). The second method lets you make a separate aliases file, so you won't have to put them in .bashrc, but to a file of your choice. First, edit your ~/.bashrc file and add or uncomment the following lines, if it is not already

if [ -f ~/.bash_aliases ]; then

. ~/.bash_aliases

fi

Save it and close the file. After that, all you have to do is create a ~/.bash_aliases file and add your aliases there, with the same format specified in the first method.

Contents of my ~/.bash_aliases file:

aneesh@aneesh-VirtualBox:~$ cat .bash_aliases

alias cs='cd;ls'


Tags: bash (Next Q)


Q: Why ~/.bash_profile is not getting sourced when opening a terminal?

Tags: bash (Next Q), environment-variables (Next Q)

Problem

I have an Ubuntu 11.04 Virtual Machine and I wanted to set up my Java development environment. I did as follows

1. sudo apt-get install openjdk-6-jdk

2. Added the following entries to ~/.bash_profile

3. export JAVA_HOME=/usr/lib/jvm/java-6-openjdk

4.

5. export PATH=$PATH:$JAVA_HOME/bin

3. Save the changes and exit

4. Open up a terminal again and typed the following

5. echo $JAVA_HOME (blank)

6. echo $PATH (displayed, but not the JAVA_HOME value)

5. Nothing happened, like if the export of JAVA_HOME and it's addition to the PATH were never done.

Solution

I had to go to ~/.bashrc and add the following entry towards the end of file

#Source bash_profile to set JAVA_HOME and add it to the PATH because for some reason is not being picked up

. ~/.bash_profile

Questions

1. Why did I have to do that? I thought bash_profile, bash_login or profile in absence of those two get executed first before bashrc.

2. Was in this case my terminal a non-login shell?

3. If so, why when doing su after the terminal and putting the password it did not execute profile where I had also set the exports mentioned above?

Tags: bash (Next Q), environment-variables (Next Q)

User: viriato


Answer by geirha

~/.bash_profile is only sourced by bash when started in interactive login mode. That is typically only when you login at the console (Ctrl+Alt+F1..F6), or connecting via ssh.

When you log in graphically, ~/.profile will be specifically sourced by the script that launches gnome-session (or whichever desktop environment you're using). So ~/.bash_profile is not sourced at all when you log in graphically.

When you open a terminal, the terminal starts bash in (non-login) interactive mode, which means it will source ~/.bashrc.

The right place for you to put these environment variables is in ~/.profile, and the effect should be apparent next time you log in.

Sourcing ~/.bash_profile from ~/.bashrc is the wrong solution. It's supposed to be the other way around; ~/.bash_profile should source ~/.bashrc.

See DotFiles for a more thorough explanation, including some history of why it is like it is.

(On a side note, when installing openjdk via apt, symlinks should be set up by the package, so that you don't really need to set JAVA_HOME or change PATH)


Answer by lgarzo

You can check if your Bash shell is started as a login-shell by running:

shopt login_shell

If the reply is off you are not running a login shell.

Read the Bash manual's invocation section on how Bash reads (or does not read) different configuration files.

Excerpt from man bash:

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.

su on the other hand also does not start a login shell by default, you have to tell it to do so by using the --login option.


Tags: bash (Next Q), environment-variables (Next Q)


Q: How to clear bash history completely?

Tags: bash (Next Q)

I want to clear all before command from history of my server. I use history -c it seems all things are cleared but when I ssh to the server,all commands are still there.

How can I clear them permanently?

Tags: bash (Next Q)

User: hd.


Answer by devav2

~/.bash_history holds the history.

To clear the bash history completely on the server. You can open terminal and type cat /dev/null > ~/.bash_history

Other alternative way is to link ~/.bash_history to /dev/null

On my Ubuntu 12.10 box, The history comes back when I login back. I guess because the history entries has a copy in the memory and it will flush back to the file when you log out. The following command worked for me.

cat /dev/null > ~/.bash_history && history -c && exit


Answer by callpraths

What to do:

In every open bash shell (you may have multiple terminals open):

history -w

history -c

Why: As noted above, history -c empties the file ~/.bash_history. It is important to note that bash shell does not immediately flush history to the bash_history file. So, it is important to (1) flush the history to the file, and (2) clear the history, in all terminals. That's what the commands above do.

Reference: http://www.giannistsakiris.com/index.php/2007/09/13/how-to-clear-bash-history-and-what-to-watch-out-for/


Answer by peter-eijlander

There's another much simpler one: running history -c on the terminal prompt and gone are all entries in the bash_history file.


Tags: bash (Next Q)


Q: Is #!/bin/sh read by the interpreter?

Tags: bash scripts (Next Q), python (Next Q)

In bash or sh, I guess anything which starts with # is a comment.

But in bash scripts we write:

#!/bin/bash

And in Python scripts, there is:

#!/bin/python

Does this mean that # by itself is a comment whereas #! is not?

Tags: bash scripts (Next Q), python (Next Q)

User: gaurav-sharma


Answer by eliah-kagan

The #! line is used before the script is run, then ignored when the script runs.

You're asking what the difference is between a shebang line and an ordinary comment.

A line starting with #! is just as much a comment as any other line that starts with #. This is true if the #! is the first line of the file, or anywhere else. #!/bin/sh has an effect, but it is not read by the interpreter itself.

# is not a comment in all programming languages but, as you know, it's a comment in Bourne-style shells including sh and bash (as well as most non-Bourne-style shells, like csh). It's also a comment in Python. And it is a comment in a variety of configuration files that are not really scripts at all (like /etc/fstab).

Suppose a shell script begins with #!/bin/sh. That is a comment, and the interpreter (the shell) ignores everything on the line after the # character.

The purpose of a #! line is not to give information to the interpreter. The purpose of the #! line is to tell the operating system (or whatever process launches the interpreter) what to use as the interpreter.

· If you invoke the script as an executable file, for example, by running ./script.sh, the system consults the first line to see if begins with #!, followed by zero or more spaces, followed by a command. If it does, it runs that command with the name of the script as its argument. In this example, it runs /bin/sh script.sh (or, technically, /bin/sh ./script.sh).

· If you invoke the script by explicitly calling the interpreter, the #! line is never consulted. So, if you run sh script.sh, the first line has no effect. If script2.sh's first line is #!/usr/games/nibbles, running sh script2.sh will not try to open the script in nibbles (but ./script2.sh will).

You'll notice that in neither case does the script's extension (.sh), if it has one, impact how it is run. In a Unix-like system, this doesn't ordinarily affect how the script is run. On some other systems, like Windows, the #! shebang line might be ignored entirely by the system, and the extension might determine what runs the scripts. (This doesn't mean you need to give your scripts extensions, but it is one of the reasons why if you do, they should be correct.)

#! was chosen to serve this purpose precisely because # begins a comment. The #! line is for the system, not the interpreter, and it should be ignored by the interpreter.

Shebang Line for Bash Scripts

You (originally) said you use #!/bin/sh for bash scripts. You should only do that if the script doesn't require any of bash's extensions--sh needs to be able to run the script. sh is not always a symlink to bash. Often, including on all remotely recent Debian and Ubuntu systems, sh is a symlink to dash.

Shebang Line for Python Scripts

You also said (in the first version of your question, before editing) that you start your Python scripts with #!/bin/sh read by the interpretor. If you mean that literally, then you should definitely stop doing that. If hello.py begins with that line, running ./hello.py executes:

/bin/sh read by the interpretor hello.py

/bin/sh will try to execute a script called read (with by the interpretor hello.py as its arguments), read will (hopefully) not be found, and your Python script will never be seen by a Python interpreter.

If you're making this mistake but not having the problem I'm describing, you're probably invoking your Python scrips by explicitly specifying the interpreter (e.g., python hello.py), causing the first line to be ignored. When you distribute your scripts to others, or use them a long while later, it may not be clear that this is necessary for them to work. It's best to fix them now. Or at least remove the first line entirely, so that when they fail to run with ./ the error message will make sense.

For Python scripts, if you know where the Python is (or is going to be), you can write the #! line the same way:

#!/usr/bin/python

Or, if it's a Python 3 script, you should specify python3, since python is almost always Python 2:

#!/usr/bin/python3

However, the problem is that while /bin/sh is supposed to always exist, and /bin/bash almost always exists on systems where bash comes with the OS, Python may exist in a variety of places.

Therefore, many Python programmers use this instead:

#!/usr/bin/env python

(Or #!/usr/bin/env python3 for Python 3.)

This makes the script rely on env being in the "right place" instead of relying on python being in the right place. That's a good thing, because:

· env is almost always located in /usr/bin.

· On most systems, whichever python should run your script is the one that appears first in the PATH. Starting hello.py with #!/usr/bin/env python make ./hello.py run /usr/bin/env python hello.py, which is (virtually) equivalent to running python hello.py.

The reason you cannot use #!python is that:

· You want the interpreter specified to be given by an absolute path (i.e., starting with /).

· The calling process would execute python in the current directory. The behavior of searching the path when the command doesn't contain a slash is specific shell behavior.

Occasionally a Python or other script that isn't a shell script will have a shebang line starting with #!/bin/sh ... where ... is some other code. This is sometimes correct, because there are some ways to invoke the Bourne-compatible shell (sh) with arguments to make it invoke a Python interpreter. (One of the arguments will probably contain python.) However, for most purposes, #!/usr/bin/env python is simpler, more elegant, and more likely to work the way you want.

Shebang Lines in Other Languages

Many programming and scripting languages, and some other file formats, use # as a comment. For any of them, a file in the language can be run by a program that takes it as an argument by specifying the program on the first line after #!.

In some programming languages, # is not normally a comment, but as a special case the first line is ignored if it starts with #!. This facilitates the use of #! syntax even though # doesn't otherwise make a line a comment.

Shebang Lines for Files That Don't Run As Scripts

While it's less intuitive, any file whose file format can accommodate a first line starting with #! followed by the full path of an executable can have a shebang line. If you do this, and the file is marked executable, then you can run it like a program...causing it to be opened like a document.

Some applications use this behavior intentionally. For example, in VMware, .vmx files define virtual machines. You can "run" a virtual machine as though it were a script because these files are marked executable and have a shebang line causing them to be opened in a VMware utility.

Shebang Lines for Files That Don't Run as Scrips but Act Like Scripts Anyway

rm removes files. It is not a scripting language. However, a file that starts #!/bin/rm and is marked executable can be run, and when you run it, rm is invoked on it, deleting it.

This is often conceptualized as "the file deletes itself." But the file is not really running at all. This is more like the situation describe above for .vmx files.

Still, because the #! line facilitates the running of a simplistic command (including command-line arguments), you can perform some scripting this way. As a simple example of a "script" more sophisticated than #!/bin/rm, consider:

#!/usr/bin/env tee -a

This takes user input interactively, echoes it back to the user line-by-line, and appends it to the end of the "script" file.

Useful? Not very. Conceptually interesting? Totally! Yes. (Somewhat.)

Conceptually Similar Programming/Scripting Concepts (just for fun)

· Scripts/programs that are multiple languages at once, for example, to simulate hashbang functionality in OSes that didn't have it.

(These programs are called polyglots, but this is not to be confused with the other sense of polyglot in software development, a program/project where different parts are written in different languages.)

· Metacommands in QBasic/QuickBASIC, which signaled to the compiler (for compiled code) options for code generation, but were part of comments and thus ignored during actual compilation/interpretation.


Tags: bash scripts (Next Q), python (Next Q)


Q: Moving from bash to zsh


Q: What to do when Ctrl-C won't kill running job?


Q: Hide current working directory in terminal


Q: How do I create a permanent Bash alias?


Q: Running programs in the background from terminal


Q: Why ~/.bash_profile is not getting sourced when opening a terminal?


Q: How to clear bash history completely?


Q: Is #!/bin/sh read by the interpreter?