0 is true, anything non-zero is false. You can test the return value of any command by examining the special $? EnvironmentVariable.
$ ls mbox ; echo $? mbox 0 $ ls mboxxx ; echo $? ls: mboxxx: No such file or directory 1
There are also special commands called true(1) and false(1) that can be used in tests:
$ true ; echo $? 0 $ false ; echo $? 1
It's probably not bash(1) beeping, but readline(3) sending a bell. You can disable this by putting:
set audible-bell none
in your ~/.inputrc file. This will remove the bell for all readline(3) enabled programs. To make it only do this for bash(1), see the readline(3) section of the bash(1) manpage.
If you are in a graphical environment, you can tell your XServer to disable all beeps for X programs (including xterm(1) and other terminals) by setting the bell volume to zero:
xset b 0
If you use gnome, then that annoying beeping can be disabled by going to System > Preferences > Sound
Find the "System Beep" tab and uncheck "Enable System Beep".
Surround the expression with $(( )), eg:
ANSWER=$((6*9))
This is equivalent to using the expr(1) program, but you will need to escape any shell special characters:
ANSWER=`expr 6 \* 9`
You could use at(1) but it's more fun to use something like this:
sleep $(($(date -d '6pm tomorrow' +%s)-$(date +%s)))
See HereDocuments.
Easy:
for i in *.files.foo; do mv $i ${i/files.foo/files-foo}; done
This lets you use sed(1)-like regexp syntax in the command line. You might want to read up on "Parameter Expansion" in bash(1).
To remove a suffix:
for i in *.files.foo; do mv $i ${i%.foo}; done
To remove a prefix:
for i in files-foo*; do mv $i ${i#files-}; done
For small ranges you can just write the numbers out:
for i in 2 3 4 5 6; do echo $i; done
On GNU systems, use the seq(1) program:
for i in `seq 50 1000`; do echo $i; done
FreeBSD has a similar program called jot.
Type Ctrl-V so the next character will be interpreted literally, then tap Tab to insert a literal Tab character.
You can redirect a program's stdout and/or stderr to places other than the terminal – eg to files on the disk, or as another program's stdin. The order that redirections happen can be important. Some examples.
Make stderr go to stdout, so you can view both of them together in less(1) or more(1):
somecommand 2>&1 | less
Get rid of stdout, and move stderr to stdout so that you can pipe it to less:
somecommand 2>&1 >/dev/null | less
The following first sends stdout to /dev/null, and then sends stderr to where stdout is now pointing (ie sends both to /dev/null, which is probably not what you want for redirection, but it's excellent for getting silent output from a command):
somecommand >/dev/null 2>&1
As an alternative, to send both stdout and stderr to the same place you can use the &> redirector:
somecommand &>/dev/null
See CshProgrammingConsideredHarmful for some trickier examples.
A useful method to debug bash scripts is to run then with bash -x; printing each line as it goes, interspersed with its output. However, you can't start a script with
#!/bin/bash -x > foo
You can, however, do this:
#!/bin/bash -x exec 1> /tmp/foo exec 2>&1
Using process substitution (see bash(1)Part4) -
gedit <(groff-2-wiki.pl bash)
This opens up the bash(1) wikified page in gedit (as a temp file like /dev/fd/63), ready to manually overview and paste into the wiki. See the file archive for the groff-2-wiki script.
When you resize a terminal, it sends a SIGWINCH signal to the process running inside it. If the current foreground process is not bash(1), but another process (eg less(1), tail(1), or whatever), then only that process receives the signal. The shell is then left with outdated size information.
The best way to fix this is to set the checkwinsize shell option:
shopt -s checkwinsize
Bash will now check the size every time it displays a prompt. Other shells (such as zsh(1)) seem to do this automatically, and don't have a corresponding option.
A one-off workaround is to send SIGWINCH to the shell yourself:
kill -WINCH $$
($$ is a variable containing the shell's own PID.)
From faqs.org:
Window and icon titles may be changed in a running xterm(1) (and most derivatives, such as gnome-terminal) by using XTerm escape sequences. The following sequences are useful in this respect:
where ESC is the escape character (\033), and BEL is the bell character (\007).
echo -ne "\033]0;''title here''\007"
In bash(1), to have the title automatically update based on who and where you are, set PROMPT_COMMAND like so:
ROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
That should configure the shell completion to be case-insensitive for the remainder of the session.
Make permanent: Create a file called .inputrc in your home directory and put this line in it:
Well, bash is listing nothing. It's ls(1) and its locale support that matter here, it has nothing to do with the Shell. But this is where you'd expect to find this tidbit.
I swear ls(1) used to list files in ASCII order. Then one day it stopped. And I didn't like it. Much swearing and cursing ensued.
$ ls -la total 3612 drwxr-xr-x 15 573 573 4096 2005-05-14 14:53 . drwxrwsr-x 4 root src 4096 2005-06-15 01:59 .. drwxr-xr-x 20 573 573 4096 2003-08-25 23:44 arch -rw-r--r-- 1 root root 17644 2005-05-14 14:44 .config -rw-r--r-- 1 root root 4376 2005-05-14 14:46 .depend -rw-r--r-- 1 573 573 18691 2002-08-03 12:39 COPYING drwxr-xr-x 32 573 573 4096 2005-04-04 13:42 Documentation drwxr-xr-x 40 573 573 4096 2005-05-14 14:45 drivers -rw-rw-r-- 1 573 573 19095 2005-05-14 14:44 Makefile drwxr-xr-x 2 573 573 4096 2005-05-14 14:49 mm -rw-r--r-- 1 573 573 14287 2003-08-25 23:44 README -rw-r--r-- 1 root root 505139 2005-05-14 14:53 System.map -rw-r--r-- 1 root root 2 2005-05-14 14:46 .version -rwxr-xr-x 1 root root 2646164 2005-05-14 14:53 vmlinux $ export LANG=C LC_ALL=C $ ls -la total 3612 drwxr-xr-x 15 573 573 4096 May 14 14:53 . drwxrwsr-x 4 root src 4096 Jun 15 01:59 .. -rw-r--r-- 1 root root 17644 May 14 14:44 .config -rw-r--r-- 1 root root 4376 May 14 14:46 .depend -rw-r--r-- 1 root root 2 May 14 14:46 .version -rw-r--r-- 1 573 573 18691 Aug 3 2002 COPYING drwxr-xr-x 32 573 573 4096 Apr 4 13:42 Documentation -rw-rw-r-- 1 573 573 19095 May 14 14:44 Makefile -rw-r--r-- 1 573 573 14287 Aug 25 2003 README -rw-r--r-- 1 root root 505139 May 14 14:53 System.map drwxr-xr-x 20 573 573 4096 Aug 25 2003 arch drwxr-xr-x 40 573 573 4096 May 14 14:45 drivers drwxr-xr-x 2 573 573 4096 May 14 14:49 mm -rwxr-xr-x 1 root root 2646164 May 14 14:53 vmlinux
If you have a shell script that passes arguments on to another program while acting as a wrapper watch carefully how you deal with arguments or you will end up accidentally eating whitespace. See the example below for a demonstration.
#!/bin/bash # Print number of arguments echo $#
#!/bin/bash # Do some stuff here # Call another program ./test.sh $@
#!/bin/bash # Do some stuff here # Call another program ./test.sh "$@"
matt@argon:/tmp$ ./wrapper.sh 0 matt@argon:/tmp$ ./safe_wrapper.sh 0 matt@argon:/tmp$ ./wrapper.sh a 1 matt@argon:/tmp$ ./safe_wrapper.sh b 1 matt@argon:/tmp$ ./wrapper.sh a "" 1 matt@argon:/tmp$ ./safe_wrapper.sh b "" 2
Note that the 'empty' argument is only preserved when $@ is wrapped in quotes (eg in safe_wrapper.sh).
readline(3) isn't correctly interpreting the escape code that delete generates. You can work around it in your terminal, but the easiest fix is to add the line
"\e[3~": delete-char
to ~/.inputrc.
Garret LeSage has posted a super useful inputrc, which fixes all sorts of keys (such as ctrl-arrow).
Here's another cool self-documented tip:
# By default up/down are bound to previous-history # and next-history respectively. The following does the # same but gives the extra functionality where if you # type any text (or more accurately, if there is any text # between the start of the line and the cursor), # the subset of the history starting with that text # is searched (like 4dos for e.g.). # Note to get rid of a line just hit Ctrl-C. "\e[B": history-search-forward "\e[A": history-search-backward
I have a bunch of remote machines with a config file that has some OPTIONS=something, and I want to set them all across-the-board to OPTIONS="foo". Locally, I would do it this way:
sed -i -e 's/OPTIONS=.*/OPTIONS="foo"/' file
This is hard to send over SSH however, as bash(1) locally likes to eat all your quotes, so they never reach the other end.
PerryLorier's most bodacious answer:
ssh site sed -i -e \''s/OPTIONS=.*/OPTIONS="foo"/'\' file
If anyone else has an answer, please add it, rather than replacing this one; I can at least understand what happens here. One set of brackets is eaten locally, and another set is sent to the other end, so the sed command ends up with 's when run on the remote host. —CraigBox
Another option:
ssh site <<'END_SCRIPT' sed -i -e 's/OPTIONS=.*/OPTIONS="foo"/' file END_SCRIPT
LawrenceDoliveiro's so-simple-you'll-kick-yourself-for-not-thinking-about-it answer:
ssh site sed -i -e $(printf %q 's/OPTIONS=.*/OPTIONS="foo"/') file
using Bash's printf builtin.
After typing the command, press Esc then press C-e
for ((i=1; i<100;i++));do echo $i; done;
Use bc
will result in : 1.2500000000 The value of the scale function is the number of digits after the decimal point in the expression. (In this case 10)
Try intermixing the two also.
if [ $bla -eq 1 -o $cars -eq 3 -o $monkeys -eq 4 ]; then echo "Westside" fi
Say you have a file called '--test'. If you wanted to use vim to edit this file then you would do:
vim -- --test
The '--' tells the command that what follows is an argument, NOT to interpret them as options.
AdrianHo: Note that not all programs accept '--' as an "end of options" marker. A more reliable method is prefixing the filename with "./", as in:
vim ./--test
If the above script makes a change to the environment, it is the environment of this shell that is changed. So if inside the script we change the directory, then when the script has finished being interpreted we will find ourselves in the new directory.
Note : This can be handy when you want to reset the shell environment variables.
Just do:
Vi mode allows for the use of vi like commands when at the bash prompt. When set to this mode initially you will be in insert mode (be able to type at the prompt unlike when you enter vi). Hitting the escape key takes you into command mode. To enable this do:
One thing I do like about vi mode, is how easy it is to edit really long commands. (Of course some will argue that I should just use a bash script instead)
When in vi mode press 'esc' to enter command mode. Now press 'v'. This will start up the default editor (as defined by the EDITOR environment variable) and your command will be displayed. Edit it to your liking (feel free to use multiple lines for loops/if statements etc), save and exit. Your command will be executed.
To escape out of vi mode simply type:
4 pages link to BashNotes: