Bash: Difference between revisions
Line 31: | Line 31: | ||
"\C- ":dynamic-complete-history #Ctrl-space |
"\C- ":dynamic-complete-history #Ctrl-space |
||
"\e ":dynamic-complete-history #Esc-space |
"\e ":dynamic-complete-history #Esc-space |
||
"\e[2~":paste-from-clipboard # Insert |
|||
</source> |
</source> |
||
Revision as of 11:01, 13 November 2008
References
- Bash Manual Page
- Bash Reference Manual
- Advanced Bash-Scripting Guide
- http://www.ss64.com/bash/index.html (find Linux shell command if you know Windows shell command, and vice-versa)
- http://tille.xalasys.com/training/bash
Shell
Commands
Listing directory content:
ls --full-time # To list files full date & time
ls -d directory-name # List directory entries, not content
# eg. ls -d /etc/rc*
ls -lS | head # List biggest files first - print only first 10 entries
ls -lt | head -n 20 # List most recent files first, print only 20 first entries
Keyboard shortcuts
Some of the most used keyboard shortcuts in Bash (excerpt from the manual pages).
C- refers to Ctrl key, M- refers to Meta key (typ. Alt+key, or Esc then key), S- refers to Shift key.
Customized keyboard shortcuts described below can be obtained by adding the following lines to e.g. your ~/.inputrc file:
"\eOA":history-search-backward #Up arrow
"\e[A":history-search-backward #Up arrow
"\eOB":history-search-forward #Down arrow
"\e[B":history-search-forward #Down arrow
"\C- ":dynamic-complete-history #Ctrl-space
"\e ":dynamic-complete-history #Esc-space
"\e[2~":paste-from-clipboard # Insert
- Note on defining new bindings
- Binding by defaults are defined in file ~/.inputrc. Alternatively they can also be defined in the start file ~/.bashrc using command bind.
- They are different method to define the binding keys
- Specifying the key Keyname, without double quotes (but always within single quotes)
- Specifying the key Keyseq, with double quotes (and single quotes)
- Specifying the key Verbatim, with double quotes, and using control-V followed by key in Bash or Vi. Note: This is a good trick to know the key sequence of special keys like arrow key.
- The binding keyseq differs depending on whether Readline is configured to support 8-bit input/output characters. Cygwin and openSUSE have different settings regarding this. To support 8-bit input/output (like in OpenSUSE), add the following to the ~/.inputrc:
set convert-meta off set input-meta on set meta-flag on set output-meta on
bind 'tab:dynamic-complete-history' #Keyname
bind '"\C-i":dynamic-complete-history' #Keyseq
bind '"<Control-V><Tab>:dynamic-complete-history' #Verbatim - <> means press the given key while editing
Commands for Moving
- forward-word (M-f, C-→, M-→, S-→)
- Move forward to the end of the next word. Words are composed of alphanumeric characters (letters and digits).
- !!! C-→, M-→, S-→ not supported in Cygwin.
- backward-word (M-b, C-←, M-←, S-←)
- Move back to the start of the current or previous word. Words are composed of alphanumeric characters (letters and digits).
- !!! C-←, M-←, S-← not supported in Cygwin.
- clear-screen (C-l)
- Clear the screen leaving the current line at the top of the screen. With an argument, refresh the current line without clearing the screen.
Commands for Manipulating the History
- reverse-search-history (C-r)
- Search backward starting at the current line and moving 'up' through the history as necessary. This is an incremental search.
- forward-search-history (C-s)
- Search forward starting at the current line and moving 'down' through the history as necessary. This is an incremental search.
- !!! Not supported in Cygwin.
- history-search-forward (↓)
- Search forward through the history for the string of characters between the start of the current line and the point. This is a non-incremental search.
- !!! Custom keyboard shortcut.
- history-search-backward (↑)
- Search backward through the history for the string of characters between the start of the current line and the point. This is a non-incremental search.
- !!! Custom keyboard shortcut.
- yank-last-arg (M-., M-_)
- Insert the last argument to the previous command (the last word of the previous history entry). With an argument, behave exactly like yank-nth-arg. Successive calls to yank-last-arg move back through the history list, inserting the last argument of each line in turn. The history expansion facilities are used to extract the last argument, as if the "!$" history expansion had been specified.
- history-expand-line (M-^)
- Perform history expansion on the current line. See HISTORY EXPANSION below for a description of history expansion.
- !!! AZERTY keyboard: press Alt-^ twice
- operate-and-get-next (C-o)
- Accept the current line for execution and fetch the next line relative to the current line from the history for editing. Any argument is ignored.
Commands for Changing Text
- delete-char (C-d)
- Delete the character at point. If point is at the beginning of the line, there are no characters in the line, and the last character typed was not bound to delete-char, then return EOF.
- backward-delete-char (Rubout)
- Delete the character behind the cursor. When given a numeric argument, save the deleted text on the kill ring.
- quoted-insert (C-q, C-v)
- Add the next character typed to the line verbatim. This is how to insert characters like C-q, for example.
- transpose-chars (C-t)
- Drag the character before point forward over the character at point, moving point forward as well. If point is at the end of the line, then this transposes the two characters before point. Negative arguments have no effect.
- transpose-words (M-t)
- Drag the word before point past the word after point, moving point over that word as well. If point is at the end of the line, this transposes the last two words on the line.
- upcase-word (M-u)
- Uppercase the current (or following) word. With a negative argument, uppercase the previous word, but do not move point.
- downcase-word (M-l)
- Lowercase the current (or following) word. With a negative argument, lowercase the previous word, but do not move point.
- capitalize-word (M-c)
- Capitalize the current (or following) word. With a negative argument, capitalize the previous word, but do not move point.
- overwrite-mode
- Toggle overwrite mode. With an explicit positive numeric argument, switches to overwrite mode. With an explicit non-positive numeric argument, switches to insert mode. This command affects only emacs mode; vi mode does overwrite differently. Each call to readline() starts in insert mode. In overwrite mode, characters bound to self-insert replace the text at point rather than pushing the text to the right. Characters bound to backward-delete-char replace the character before point with a space. By default, this command is unbound.
Killing and Yanking
- kill-line (C-k)
- Kill the text from point to the end of the line.
- unix-line-discard (C-u)
- Kill backward from point to the beginning of the line. The killed text is saved on the kill-ring.
- kill-word (M-d)
- Kill from point to the end of the current word, or if between words, to the end of the next word. Word boundaries are the same as those used by forward-word.
- backward-kill-word (M-Rubout)
- Kill the word behind point. Word boundaries are the same as those used by backward-word.
- unix-word-rubout (C-w)
- Kill the word behind point, using white space as a word boundary. The killed text is saved on the kill-ring.
Numeric Arguments
- digit-argument (M-0, M-1, ..., M--)
- Add this digit to the argument already accumulating, or start a new argument. M-- starts a negative argument.
Completing
- complete (TAB)
- Attempt to perform completion on the text before point. Bash attempts completion treating the text as a variable (if the text begins with $), username (if the text begins with ~), hostname (if the text begins with @), or command (including aliases and functions) in turn. If none of these produces a match, filename completion is attempted.
- possible-completions (M-?)
- List the possible completions of the text before point.
- insert-completions (M-*)
- Insert all completions of the text before point that would have been generated by possible-completions.
- dynamic-complete-history (M-SPACE,C-SPACE)
- Attempt completion on the text before point, comparing the text against lines from the history list for possible completion matches.
- !!! Must use combination Esc + Tab. Custom combination in Cygwin.
Miscellaneous
- prefix-meta (ESC)
- Metafy the next character typed. ESC f is equivalent to Meta-f.
- undo (C-_, C-x C-u)
- Incremental undo, separately remembered for each line.
- !!! AZERTY keyboard: press Control--.
- revert-line (M-r)
- Undo all changes made to this line. This is like executing the undo command enough times to return the line to its initial state.
- set-mark (C-@, M-<space>)
- Set the mark to the point. If a numeric argument is supplied, the mark is set to that position.
- exchange-point-and-mark (C-x C-x)
- Swap the point with the mark. The current cursor position is set to the saved position, and the old cursor position is saved as the mark.
History
Some examples (assume that magic-space is mapped to Space)
echo 12 34
!! #execute previous command
!1 #execute command n°1
!-2 #execute penultimate command
echo 12 34
^12^56^ #execute previous command, replacing 12 with 56. Quick for !!:s/12/56/
!!<space> #Example of magic space
ech !-2<space> #... also works anywhere in the current line
Script Quick Tutorial
Warning / Common pitfalls
A set of warnings / common pitfalls when writing script in Bash:
Description | Example |
---|---|
Space! - Don't forget to add spaces whenever necessary, in particular around brace in function definition, or in test conditions for ifs. |
if -space- [ -space- -f /etc/foo -space- ]; then ... |
Quote - Always quote parameters, variables passed to test in if ... then ... else: |
if [ "$name" -eq 5 ]; then ... |
For loops with file - Use simply * to list files in for loops, not `ls *`: |
for file in *; cat "$file"; done # SUCCEEDS, even if white space
for file in `ls *`; cat "$file"; done # FAILS miserably
|
Environment
export MYVAR=myvalue && command-to-execute #MYVAR defined for the current shell and invoked shell
MYVAR=myvalue && command-to-execute #MYVAR defined for the current shell
MYVAR=myvalue command-to-execute #MYVAR only defined for the subsequent command
Quotation
echo "var is $var"
|
String enclosed in double quote is treated as a single argument. Variable and special characters are expanded. |
echo 'it costs $10'
|
Same as double quote, but variables are not expanded. |
x=`expr $x + 1`
|
Back-quote is replaced by the result of the invoked command. |
x=$(expr $x + 1)
|
Same as back-quote, but somewhat clearer |
x=$(($x + 1))
|
Built-in Bash expression evaluator. Accepts operation are +, -, *, /, %. |
Variable Expansion
% VAR=myvar.pattern && echo ${VAR%%.pattern}
myvar
|
Use ${i%%pattern} to delete given trailing pattern. Use a single % for shortest matching pattern. memo: % at the end as in 100%. |
% VAR=pattern.myvar && echo ${VAR##pattern.}
myvar
|
Use ${i##pattern} to delete given heading pattern. Use a single # for shortest matching pattern. memo: # at the beginning as in #comment. |
% VAR=some.find.text && echo ${VAR/find/replace}
some.replace.text
|
Use ${i/pattern/text} to replace given pattern with given text. |
If ... then ... [elif ...] ... else ... fi
The basic syntax for if-then-else sequence control is
if list; then list; [ elif list; then list; ] ... [ else list; ] fi
Test conditions can be written using command test, or equivalently using the square brackets.
if test -f /etc/foo; then echo file found; else echo file NOT found; fi
if [ -f /etc/foo ]; then echo file found; else echo file NOT foudn; fi
Here's test's options:
-d FILE # Check if the file is a directory
-e FILE # Check if the file exists
-f FILE # Check if the file is a regular file
-g FILE # Check if the file hash SGID permissions
-r FILE # Check if the file is readable
-s FILE # Check if the file's size is not 0
-u FILE # Check if the file has SUID permissions
-w FILE # Check if the file is writeable
-x FILE # Check if the file is executable
NBR1 -eq NBR2 # Check is NBR1 is equals to NBR2
NBR1 -ne NBR2 # Check if NBR1 is not equals to NBR2
NBR1 -ge NBR2 # Check if NBR1 is greater than or equal to NBR2
NBR1 -gt NBR2 # Check if NBR1 is greater than NBR2
NBR1 -le NBR2 # Check if NBR1 is less than or equal to NBR2
NBR1 -lt NBR2 # Check if NBR1 is less than NBR2
STR1 = STR2 # Check if STR1 is the same as STR2
STR1 != STR2 # Check if STR1 is not the same as STR2
-n STR # Evaluates to true if STR is not null
-z STR # Evaluates to true if STR is null.
Conditions can be combined with && and ||:
if [ $x -ge 5] && [ $x -le 10]; then ...
if [ $x -gt 5] || [ $x -lt 10]; then ...
Some examples:
if [ "$name" eq 5 ]; then echo one; else echo two; fi
if [ -d ~/var ]; then touch ~/var/done; else { mkdir ~/var; touch ~/var/done; } fi # braces { ... } are optional here
Alternative: Using && and ||
Using && and ||, one can also build a if ... then ... else statement:
[ -f /etc/hosts ] && { echo one; echo two; } || { echo three; echo four; }
WHILE / UNTIL Loops
Syntax is
while list; do list; done until list; do list; done
Some examples of While loops:
while true; do
echo "Press CTRL-C to quit."
done
# Faster alternative using Bash built-in colon feature
while :; do
echo "Press CTRL-C to quit."
done
# A more complete example
x=0; # initialize x to 0
while [ "$x" -le 10 ]; do
echo "Current value of x: $x"
# increment the value of x:
x=$(expr $x + 1)
sleep 1
done
Some examples of until loops:
x=0
until [ "$x" -ge 10 ]; do
echo "Current value of x: $x"
x=$(expr $x + 1)
sleep 1
done
FOR Loops
There are 2 syntax for for loops:
for name [ in word ] ; do list ; done for (( expr1 ; expr2 ; expr3 )) ; do list ; done
The first syntax enumerates a list, as in:
# Counting from 1 to 10...
for dots in 1 2 3 4 5 6 7 8 9 10; do echo -n "$dots... "; done;
echo 'Done !'
# Enumerating a list
for fruit in Apple Pear Cherry; do
echo "The value of variable fruit is: $fruit"
sleep 1
done
# Acting on a directory list:
for file in *; do
echo "Adding .html extension to $file..."
mv $file $file.html
sleep 1
done
# On several lines
for f in $(seq 33296 33330); do
wget "http://i.techrepublic.com.com/gallery/${f}.jpg"
done
# On a single line
for i in `seq 278 328`; do wget http://i.techrepublic.com.com/gallery/33$i.jpg; done
case ... in ... esac
The syntax is
case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
Some example
x=5 # initialize x to 5
# now check the value of x:
case $x in
0) echo "Value of x is 0."
;;
5) echo "Value of x is 5."
;;
9) echo "Value of x is 9."
;;
*) echo "Unrecognized value."
esac
Functions
Functions are like aliases, but accept parameters:
function myfunc1() { echo "$2"; echo "$1"; }
myfunc2() { MYVAR="$1"; echo Another $MYVAR function; } #The keyword ''function'' is optional
Interactivity
Read User's password
Reading input from user is done with the commands read. To prevent password echo on display, one can use the command stty:
###### Preventing echo with stty ######
read -p "Username: " uname
stty -echo
read -p "Password: " passw; echo
stty echo
Preventing password echo using option -s:
###### Using -s ######
PASS="abc123"
read -s -p "Password: " mypassword
echo ""
[ "$mypassword" == "$PASS" ] && echo "Password accepted" || echo "Access denied"
Complete solution:
###### Complete solution ######
USER=wbi\\titeuf
echo "Mounting windows share... Please type password for user $USER..."
# time-out after 60sec, raw input no escaping, no echo, prompt
read -t 60 -r -s -p "Password: " PASSWORD
# delete prompt line
echo -e -n "\r"
mount -t smbfs -o username="$USER",password="$PASSWORD",iocharset=iso8859-1,codepage=cp437 //windows-host/C$ /mnt/c
mount -t smbfs -o username="$USER",password="$PASSWORD",iocharset=iso8859-1,codepage=cp437 //windows-host/D$ /mnt/d
mount -t smbfs -o username="$USER",password="$PASSWORD",iocharset=iso8859-1,codepage=cp437 //windows-host/F$ /mnt/f
# delete password variable
PASSWORD=------------------------------------
PASSWORD=abcdefghijklmnopqrstuvwxyz0123456789
PASSWORD=------------------------------------
Signal trapping
Use trap to trap signals send to a Bash script, and redirect execution to a given function/command.
#Trap Ctrl-C (signal SIGINT) by executing function "sorry"
trap sorry INT
sorry() { echo "I'm sorry Dave. I can't do that."; sleep 3; }
Signals can also be ignored or reset.
#reset the trap:
trap - INT
#do nothing when SIGINT is caught:
trap " INT
Miscellaneous
Use eval to execute the output (stdout) of a process | eval 'dircolors'
|
Use $$ as file name suffix or prefix to create unique name for temporary file | touch /tmp/mytmp.$$
echo some text>/tmp/mytmp.$$
cat /tmp/mytmp.$$
|