Valid
	XHTML 1.1! Valid CSS!
Created 2002-01-01   Modified 2007-02-15
Chelton Evans

Bash Notes home

Vi and Vim
Unix
Unix Admin
ftp
    Scripting with kermit
Bash
    Local Variables
    For Loop
    Files as Variables
    Arithmetic
    Functions
    Scripts
    eval
    String Processing
Emacs
Info
awk and sed
Perl

# in command mode over text to do text searches.
number n yy to copy n lines, p to paste
Ctrl-v ESC for ^[ and Ctrl-v carriage return for ^M
w - from cursor to end of word including space (e - no space)
$ object from cursor to end of line
0 beginning of line
^ first non-blank
{ previous blank line
} next blank line
n+ or n- to go forward or backward in the file where n is a number
d delete
dd and p for deleting line and pasting line below cursor
r replace character under cursor
ctrl-f forward one screen
ctrl-b back one screen
ctrl-d forward half screen
ctrl-u back half screen
H   top of screen
M   middle of screen
L   end of screen
c for change eg cw
ctrl-g for position and file status
G for end of file
number-shift-g goto number
/ and ? forward and backward searches n repeat, :set ic to ignore case % matching ([])
:#,#s/old/new/g replace between lines # and #
:%s/old/new/g replace whole file
:e to reload the file and :e filename to load a new file

:! to execute commands eg 
   :w temp.txt   write file to temp.txt
   :!ls -clt     see it
   :!rm temp.txt  remove it
   :!ls -clt     confirm removal

o and O - insert line below and above
shift+j to delete right of the cursor, deletes carriage returns!
n i x ESC to insert x n times before cursor

Vim options can be set in the .vimrc file in the home directory.

:set nocindent
:set cino=e-2   :set shiftwidth=2     Changed indent for C++ as the default sux. See :h cinoptions.
set number - to set line numbers.

ctags generates a tags file containing definitions headers. :mak,

To load a session at startup
gvim -S Session.vim
mks
  make a Session.vim, ! to overwrite.
~   to toggle case.
ddp   swaps current and next line.
*p   put resister into document.
:reg %   display file name.

Unix

tar -cf archive.tar * to create,tar -xf for extracting, tar -tvf for viewing
gzip filename, gzip *, gunzip on filename.gz files
bzip2 filename to compress, bunzip2 filename.bz2 or bzip2 d filename.bz2 to uncompress.
history | grep pattern
!339 runs command 339
head -n 20 first 20 lines
$OLDPWD previous directory
touch --m -t 200401010000 temp.xml changes the files modified time.

POSIX
The chmod can be used to change a file in two ways. It has user categories : u=User, g=Group, o=Other . And file permissions : read=4 write=2 excecute=1. Symbolically { r,w,x }. Symbolically overwrite categories or numerically overwrite all permissions in one hit.

-rw-rw-r--     chmod +x temp01.txt     -rwxrwxr-x
-rw-rw-r--     chmod 777 temp01.txt     -rwxrwxrwx
-rw-rw-r--     chmod 604 temp01.txt     -rw----r--
-rw-rw-r--     chmod g= temp01.txt     -rwx---r--
-rw-rw-r--     chmod o=x temp01.txt     -rw-rw---x
Recursively set file permissions.
find . -type f -exec chmod 644 {} \;
find . -type d -exec chmod 755 {} \;
find . -type d -print0 | xargs -0 chmod 755
find . -type f | xargs chmod 644
umask 2 = 2' = 775 permisions. This is anded with the file creation request.

# -en "\a"   beep
ctrl + c kill job jobs look at users jobs
kill -9 %1 after ctrl+z

ls -al /var list all including . ..
ls -al --ignore=.. --ignore=. /var
ls --ignore=*.h
ls -ld /var only list the file(no recursion)
ls -d \.* list hidden files

find ~/base/ -mtime -7   finds files 7 days old
chsh -s bash possible shells in /etc/shells file
ln -s "/e/Documents and Settings/chel/My Documents" mydoc symlink

Encryption/Decryption with OpenSSL
Encrypt
openssl des3 -salt -in file02.txt.tar -out file02.txt.tar.des3
Decrypt
openssl des3 -d -salt -in file02.txt.tar.des3 -out file03.txt.tar
To pass the password for use in automated scripts
tar -zcf - t3 | openssl des3 -salt -out t3.tar.gz.des3 -k password

shred -uz file - good practise to shred sensitive docs,

# /usr/sbin/visudo
harry2 ALL=(root) NOPASSWD:/home/zero/scripts/killdir01.sh
[harry2@localhost]$ sudo /home/zero/scripts/killdir01.sh

This allows one person to run the command. Lets create a group called svngroup.
%svngroup ALL=(root) NOPASSWD:/home/zero/scripts/killdir01.sh

ftp

lcd to change the local directory
put to upload
! to execute command on local sys
help

prompt - turns of interactive mode.
mput *.css

Scripting with kermit

Create a script file called s01.txt .

#!/usr/local/bin/kermit +
ftp open fluxions.balder.prohosting.com /user:fluxions /password:secret 
if fail exit 1 Connection failed
if not \v(ftp_loggedin) exit 1 Login failed
ftp cd p1
ftp dir
ftp bye
exit

To execute the script
$ kermit s01.txt

An error strategy for kermit scripts is to print out the line of code that failed in the script and exit. eg
ftp cd drivers
if fail exit 1 cd drivers: \v(ftp_message)

ftp put /recursive *
ftp put /recursive /update *

I was having a little trouble with deleting recursively with ftp so I used an open source gtfp.

Right clicking on the directory of right panel window gives a delete option. This windows program is very easy to use. However someone else's stupidity has caused me so much grief. Why ftp does not have a mv or delete on a directory is incredible. Years of computer science and ftp is a monument to their stupidity and propensity for stupid people to waste other peoples time. Can you imagine the amount of time wasted by deleting a directory and having to recopy all the entries again. Just deleting with gftp is taking me over two hours. The idiots. Multiply this by every single ftp user experiencing this. You have to come to the conclusion that whoever did ftp knows nothing about an operating system or the human cost of their actions. They are completely incompetent. How many years has this gone on for? And I thought Microsoft were bad.

Bash

The if command in bash has the following syntax.
if [ test ]; then
    ... ;
fi;

Bash is a line driven language. By this I mean that there can be compilation errors in code if the return character is deleted. For example putting the if then construct on one line. For this reason disciplined coding needs to be implemented. Here is an example of the if then else construct. Ultimately this is the programmers decision on whether to write on one or multiple lines, but on occasions I have found writing code on one line breaking so I try to be disciplined and put it across several lines.

if [ -e graphmisc.cpp ]; then
    echo graphmisc.cpp file already exists;
else
    ln -s ../proj/graphicslib/graphmisc.cpp graphmisc.cpp
fi

.sh header #!/bin/sh
scripts are run in their own environment

Initializing a local variable.
    local locations=`find -name update.sh`;

$ mount -bs G: /g4 produces
G: on /g4 type system (binmode)
umount to unmount
For zip drive, login as root, make sure another application has not got the zip drive and then mount /mnt/zip
/etc/fstab

declare - useful for looking to see if definition of function has been updated
write func in .sh file, input it through source filename, then execute the function by name

local i
for i in `find . * | grep .keep`; do rm -f $i; done
for i in `find . *`; do if [ ! -d $i ] && [ -x $i ]; then echo $i; fi; done;
find . -name \*.sh
grep "([^()]*)a" file
  [] used to search for non-matches by placing a carat inside square brackets at front. eg (hello)a matches
grep "for_each" *   searches all files in current directory
grep "^[[:space:]]*hello[[:space:]]*$" file $ matches the end of the line and ^ matches the beginning, aim : get a line with only "hello" on it
grep "$HOME" file   searches file for the name of your home directory, grep '$HOME' file   searches for string $HOME
grep DEF *wrl | grep coord   searches for DEF and coord on same line
grep "I am a \(cat\|dog\)" * "I am a cat" or "I am a dog"
| grep -v .txt Invert search with -v option.
grep map_var `find . -name \*.cpp` Searches through all *.cpp files for map_var occurrence.
ls | grep '.*.txt\|.*.xml' Similar to ls *.txt *.xml , but grep can invert. .* matches everything including space.

double tab to list possibilities eg com{double tab} shows com* declarations
To enter a command on multiple lines \shift+return.
yap to view dvi files eg $ yap gmp-man-4.0.1.dvi
diff -r -q ${base} ${base}/../temp/backup/base
  - used recursive and brief options

Pattern matching. # deletes left to right. % deletes right to left.
declare t1=./p1/p2/crap
echo ${t1#*/}
results in p1/p2/crap.
echo ${t1##*/} results in crap.
echo ${t1%%/*}; results in ..
variable#pattern
Getting file extension from a filename:   declare t2=crap.txt.bak; echo ${t2##*.}; results in bak

String substitution.
declare t01="my life"
echo ${t01/my/xx}
xx life
Substituting all matches.
declare t02="../graphicslib/graphmisc.h"
echo ${t02//\//\\\/}
..\/graphicslib\/graphmisc.h

Assigning a default value by testing for a null or empty string. If $3 is not given the value of 1 is assigned to k. local k=$3
k=${k:-1}

Another way produced an error message. ${k:=1}.
To test for a variable that is not null or empty
if [ ${k:+1} ]; then

$? gets the return value of a program.
To return a value from a bash script, the last function entered has its return value returned.
./prog 2>&1 | tee prog.txt to display and capture program output.
su super user.
script log.txt redirects standard output to file, end with exit.
<command> 2>&1 | head redirects error messages.
tail -f file follows the file writing changes to terminal. eg programming graphics, redirect messages to file and view while interacting with the application.
(time ls > t1.txt) >& t2.txt sends the result of the ls command to file t1.txt. The timmings which are sent to the output are redirected to the file t2.txt.

File Attribute Operators, take from p122 Ch5 Learning the Bash Shell - O'Reilly : C. Newham & B.Rosenblatt.

-d file file exists and is a directory
-e file file exists
-f file file exists and is a regular file
-r file You have read permission on file
-s file file exists and is not empty
-w file You have write permission on file
-x file You have execute permission on file
-O file You own the file
-G file file's group ID matches yours
file1 -nt file2 file1 is newer than file2
file1 -ot file2 file1 is older than file2
  if [ -e "$1" ]; then echo file exists; fi
  if [ -d "$1" ]; then echo directory; fi
  if [ -w "$1" ]; then echo write; fi
  if [ -r "$1" ]; then echo read; fi
  if [ -x "$1" ]; then echo execute; fi

String Processing

I prefer to process in strings rather than files. It has been commented that Bash lacks string processing facilities. There is a constant interplay between file and string processing. Awk, Sed and Perl can be used here.

Sed can be used to process strings directly. For example to find if a substring exists in a string
local i="system abc/123 def.ghj"
e3=`echo $i | sed -n '/def/p'`
if [ $e3 == "" ]; then echo "not found"...

Converting between files and strings.
# Write the file to a string.
declare filetostringval
function filetostring()
{
    local filetostringi
    filetostringval="";
    for filetostringi in `cat $1`; do
        filetostringval=$filetostringval" "$filetostringi;
    done;
}
...
filetostring temp.txt
local s=$filetostringvar
Converting a string to a file.
`cat s` > temp2.txt

This uses a global variable to pass out the resulting data. I prefix the function name to give an object orientated environment, especially to avoid variable name collisions.

Here is function to trim leading and trailing whitespace.
# Trim leading and trailing spaces from a variable. # 1: variable name.
function stringtrim
{
    local stringtrimarg="$1=\`echo \$$1 | sed -e 's/^ *//' -e 's/ *$//'\`"
    eval "$stringtrimarg"
}
...
local a=" happy "
stringtrim a
#a="happy"

This uses a reference like calling convention giving bash functions the ability to pass data out in variables.

function readfilelinebyline
{
    local aline
    while read aline; do
        echo "$aline"
    done < testscript01.txt
}
Reads lines from a file into variable aline with each iteration.

Local Variables

I have just spent a few days tracking down a bug in a bash script. The bug was only mild but no matter what I did it would not go away. It was one of those irritating bugs that worked for the majority of cases so seemed harmless and easily solved.

It would be fair to say that Bash is not a strongly typed language. So when I finally tracked down the bug it was because I used i to iterate in two functions, one which called the other and the collision only occurred in a particular case.

So while this may seem a lengthy discussion it is here to save me further grief.

Define all variables inside functions as local or with declare. By default the scope is the whole shell!

Another problem was when I had i as a local variable and called a function which had i as a global variable. It rewrote over my local variable. So be aware that functions called see the variables and can modify them.

For Loop

The for loop evaluates in the bash environment.
local i
for i in *.h *.cpp; do
    cp ${i} ${i}.txt;
done;

Finds all the files beginning with a period.
for i in `find . -name .\*`; do
   echo ${i};
done

Iterate over a list of strings.
local filetypes="png html"
local i
for i in ${filetypes}; do
    cp *.${i} temp
done;

Metacharacters can be a problem in loops. Here the output of the echo command is different from iterating over the output. The commented out code produces the desired output.
echo cat mat abc\\/
for i in `echo cat mat abc\\/`; do
# for i in `echo cat mat "abc\/"`; do
    echo ${i}
done;
produces

cat mat abc\/
cat
mat
abc/

In this case it is easier to use strings.
local i
local k="cat mat abc\/"
for i in ${k}; do
echo ${i}
done;

Using variables in loops is expected. But how variables interact is part of the bash shell. Command substitution is tricky. Here is an example where the metacharacter / must be back slashed in the sed command. Since variables are used we also need the eval command.

local arg1
local arg2
local k="cat mat abc\/"
for arg1 in ${k}; do
    arg2=${arg1}crap
    eval sed 's/${arg1}/${arg2}/g' q01.txt
done;

eval

Command substitution and command line processing use quotes, double quotes, ... to do some job but this can be complex as the parsing rules are difficult to understand.

For my sanity and yours here is a technique to program and have it work. The motivation comes from using variables with metacharacters which get interpreted differently and so expressions can not be substituted into other expressions without the meaning changing.

For example the following failed because the space character interfered with eval.
local k="zpr"
for arg1 in ${k}; do
    arg2="<a\\ href=\"${arg1}.h\">\\ ${arg1}.h<\/a>"
    eval sed 's/${arg1}.h/${arg2}/g' Makefile
done;

The issues lie in quote interpretation,... which is difficult. Instead I threw away this and got a command line instance working. Then the trick is to get the same text string as the working command line. So we are really doing the work for the interpreter by doing the substitutions ourselves in strings. This is much more sane than the standard approach.

arg3 is where the substitution occurs. Further the variable can be printed so it is known what is going to be evaluated, unlike the situation where substitution accrues and this can not be easily seen.
local k="zpr"
for arg1 in ${k}; do
    arg2="<a href=\"${arg1}.h\">${arg1}.h<\/a>"
    arg3="sed 's/${arg1}.h/${arg2}/g' Makefile"
    eval ${arg3}
done;

Another useful use for eval is with indirect references to variables. Here is a general purpose function to add a string to the end of a list of strings. Because of a possible name collision with the local variables I have prepended the functions name to the variable.
# 1: list name
# 2: value added to list
function stringlistadd
{
    local stringlistaddtemp="$1=\"\$$1 $2\""
    eval "$stringlistaddtemp"
}

Files as Variables

Unix can be fucking irritating with respect to knowing how to implement and use command options. A technology that requires a huge memory to remember every case is bad, despite its stability it should be fixed (progressively made easier through public standardization ).

As I am a simple person I have been looking at using files to store intermittent data because they seem to have advantages over pipes: what you do is clear and easy.

Consider the following with pipes if you must. Essentially the output of two commands is added together.
    local filetmp=/tmp/temp5.txt
    find . -name \*.xml > $filetmp
    find . -name \*.html >> $filetmp

Iterating over the file.
    local filetmp=/tmp/temp5.txt
    for k in `cat $filetmp`; do
        echo $k
    done

There is probably someone who knows Bash better and can do all this stuff with variables allown.

Here is another problem solved with files as variables. Find the files modified in the last k days and sort by time.

#Remove carriage returns and replace with space.
function filetostring()
{
  s="";
  local i
  for i in `cat $1`; do
    s=$s" "$i;
  done;
  echo $s;
}

function filesortbytime()
{
  echo "ls -al -t " > /tmp/t1.txt;
  find . -mtime -$1 -type f >> /tmp/t1.txt;
  filetostring /tmp/t1.txt > /tmp/t2.txt;
  bash /tmp/t2.txt;
}

The strategy is to form a string with all the arguments. Unfortunately Unix makes nested function calls extremely difficult. Something that you would think should be solved by now. Consider a better solution posted on the net.

function filesortbytime2()
{
  find . -mtime -$1 -type f | xargs ls -al -t
}

The pipe along with xargs is using the output of the first command as an input into the second command. Well I just learned something new. Thanks Unix.

Handle Too-long Command Lines
Example
ls *jpg fails
bash: /bin/ls: Argument list too long
This succeeds
find . -type f -name "*.jpg" | more
xargs takes a command and makes dynamically makes commands.
find . -mindepth 1 -maxdepth 1 -type f -name "*.jpg" | xargs -l56 -i mv {} ./d018/
I believe {} substitues the filename/s. xargs controls overflowing command line buffer, -l56 to pass maximum 56 files to mv command so xargs services do not overflow.
find . -name "*.jpg" -print0 | xargs -0 ls
With -exec this took over 20 times longer.
find . -name "*.jpg" -exec ls {} \;

for ((a=INIT; a <= LIMIT ; a++))  # Double parentheses, and "LIMIT" with no "$".
do
  echo "$bs$a"
  echo -n "$bs"      # no return
  if [ $a -lt 10 ]   # less than 10
    then echo -n 0
  fi
  echo "$a"
done     

Generate a temporary file filename.
local tempfile=/tmp/tempfile`date +%s``date +%N`.txt

Arithmetic

Surrounding expressions in double parentheses and execute in a C style. For example to set a variable i to the value of one.
(( i = 1 ))

This syntax replaced the older syntax and is much easier and sane to use. Also the square bracket test can be replaced. Heres a while loop. Notice that the if then statement has ; separators. If these are not there then the commands must be on their own lines.

  while (( $i <= 117 )) 
  do
    if (( $i == 114 )); then echo fku; fi
    echo ${i}
    (( i++ ))
  done
109
110
111
112
113
fku
114
115
116
117

The main thing is that this code is easy to change. I do not have to look up the -ne -lt or whatever command to find the right comparison operator.

Functions

function name
{
    ...
}

In bash functions are called with string arguments. Bash can return a value but it is closely associated in meaning with a programs exit status, therefore never use bash to return values in the traditional sense of a function.

Instead values are passed out of functions through global variables. I combine this with a convention on the variable names such that the function name is prefixed to the variables name. Using this convention you can turn a functional programming language into an OOP language by following the convention.

Consider the following example of a function to convert a number less than 1000 into three digits. So 20 is represented as 020 .

declare digit3number
function digit3
{
  local x
  (( x = $1 ))
  if (( x < 10 )); then digit3number=00${x}
    return
  fi

  if (( x < 100 )); then digit3number=0${x}
    return
  fi

  digit3number=${x}
}

# Example of using digit3 function.
function f2
{
  local i
  (( i = 7 ))
  while (( $i < 10 ))
  do
    digit3 ${i} 

    echo ${digit3number}

    (( i++ ))
  done

}

f2

Produced

007
008
009

Functions can be used to to tasks with a variable number of arguments. Here is the technique where the arguments to a function are iterated over.

function demo_arg_iteration
{
    local k=1
    local kmax=$#
    while (( k <= kmax ))
    do
        echo $1
        (( k++ ))
        shift
    done
}

demo_arg_iteration have a good day

Calling the script with the demo_arg_iteration
$ bash t1.sh
have
a
good
day

Learning Bash

a001.sh   - pattern matching
a002.sh   - cut
a003.sh   - revbackup
a004.sh   - recursively change permissions

Scripts

Bash functions can be written and collected together in scripts. Scripts allow automation of tasks.

There are two basic reasons to execute a script. The first is to do some task. The second is to load the functions into the shell so you can interactively use them.

For example I have some function definitions in makesimlinks.sh and I want to execute one of them.
$source makesimlinks.sh
$openglsimlinksmake

When I start my bash shell I have a load of functions and definitions that I want inside my bash shells. So similarly I read them into the bash shell by editing the .bashrc file. Inside this file is the following.
source ~/base/p1/comsci/sh/chel.sh

chel.sh - Environment settings script in Linux.

The other way to use a bash shell is to have it execute a task when called. For example in my workspace the generic term for a script is update.sh . Here is an example where calling the script results in an action taken.

#!/bin/sh

function copy
{
  local i;
  for i in *.xml *.html; do
    cp ${i} ${i}.txt
  done
}
copy
updateworkspace.sh
p1/math/calculus/number/update.sh
p1/comsci/dot/update.sh
p1/comsci/css/update.sh
p1/comsci/sh/a004.sh
p1/comsci/sh/a001.sh
p1/comsci/sh/temp1.sh
p1/comsci/sh/script_html.sh
p1/comsci/sh/a002.sh
p1/comsci/sh/a007.sh
p1/comsci/sh/update.sh
p1/comsci/sh/a006.sh
p1/comsci/sh/a003.sh
p1/comsci/sh/upload01.sh
p1/comsci/sh/chel.sh
p1/comsci/sh/a005.sh
p1/comsci/java/code/t1.sh
p1/misc/prob/update.sh
p1/misc/proj/hand.sh
p1/misc/proj/update.sh
p1/misc/stl/update.sh
p1/misc/opgl/update.sh
p1/misc/java3d/update.sh
update.sh

Linux - on my RedHat box

Executables placed in /usr/bin.

ispell file
kword
dia
maxima
mplayer -speed <ratio value> -loop 0 -fps <int> -sstep <int> -double -fs -nosound
mozilla file:<file name> The file name needs to be an absolute path from / .
eg mozilla file:/home/zero/index.html
xpdf file.pdf
gqview file.jpg
kghostview file.ps
kedit
konsole
xcdroast
redhat-config-network
ApplicationDescriptionLocation
gvimeditor/usr/X11R6/bin/gvim
nediteditor/usr/X11R6/bin/nedit

Mtools - DOS fs in Linux

The Unix way first.
# mount -t msdos /dev/fd0 /mnt/floppy
# umount /dev/fd0
  or   # umount /mnt/floppy

I have grapped useful info from YoLinuxTutorial: .

The zip drive is accessed by z: instead of the floppy a:, however it needs to be configured, my default is /dev/sdb4 .

mdir a:
mdir -a a: Directory listing including hidden files
mcopy a:dosfile   unixfile
mcopy -t file1 file2 Handle ^M translation on text files.
mcopy -/ a: ./ Copy recursively through lower directories.
mdel a:dosfile
mdu
fdformat /dev/fd0H1440
mformat a:
Format a floppy for DOS/FAT16 (2 steps)
mlabel a:label_name Floppy label (11 char max)
mren a:file1 a:file2
mmd
mrd Rename DOS directory.
mcd Change default directory on floppy.

Emacs

C-   Ctrl+
M-   Alt+
C-A beginning of line
C-E End of line
C-D Delete
M-DEL backward word delete
M-D Delete word forward
M-F   Forward one word
M-B   Back one word
C-X C-W   write file
C-X C-S   save current file
C-_ undo
C-V   scroll up
M-V   scroll down
    C-P             Previous
C-B      C-F      Back   Forward
    C-N              Next
C-K   delete from current cursor to end of line
C-S   isearch-forward
C-R   isearch-backward

Info

n - next
p - previous
moving around screen: space is forward, backspace is back, ctrl+L redisplays.
Menu moving m menuname

awk and sed

awk and sed are line based processing programs, and at times suffer because the processing is not tag based. sed is really vi at the command line.

awk '/h1/,/h2/' datafile - matches patterns

The editors are line based and not tag based processing which often is needed.

I talked with a couple of people from school and the usual way is to use the unix shell. eg store and process intermediate strings, manage temporary variables and use the shells pattern matching abilities.

Examples

List file extensions in the current directory with bash.
    for k in `ls | sed -n '/\./p'`; do
        echo ${k##*.}; done

Splitting strings.
echo "ball parc playerz" | awk 'BEGIN{ FS="parc" } { print $1 "\n" $2 }'

Replacing the space character with a new line character.
    sed 's/ /\n/g' datafile.txt
Replacing a MS ^M
    :s/ctrl+v+return/\r/g

Given a file of lines containing the name class, match the lines with the first field class and extract the second field.
    $ awk '/^class/{print $2}' tmp01.txt
The carrot character is the start.

References   autopackage , Advanced Bash-Scripting Guide

Perl

Finally came to Perl when programming in Bash was not enough. The language is very free, is close to the system and can make system calls.

$perl -le 'print 150/12.0'
#!/usr/local/bin/perl
  Header in perl file. In Unix can make the file executable.
./testprog instead of perl testprog.
Extension .pl
$num=10;
$num++;

(-e $fname) || print "File $fname does not exist.\n";
(-e $fname) && print "File $fname does exist.\n";

for loops
for ($x=0; $x <= $#names; $x++)
    { print "$names[$x]\n"; }
for $x (0 .. $#names)
    { print "$names[$x]\n"; }
foreach $i (@names)
    { print "$i\n"; }
$_
is a default variable used by Perl when no variable is given.
foreach (@names)
    { print "$_\n"; }

@names=('Mrs Smith','Mr Jones','Ms Samuel','Dr Jansen','Sir Philip');
@medics=('Dr Black','Dr Waymour','Dr Jansen','Dr Pettle');
foreach $person (@names)
{
    print "$person\n";
    if ($person=~/Dr /)
    {
        foreach $doc (@medics)
        {
            print "\t$doc\n";
            if ($doc eq $person)
            {
                goto docfound;
            }
        }
    }
}
docfound:;

system("ls")
$fname="g001.txt";
$fpath="/tmp/";
print $fname,"\n";
print $fpath,"\n";
$ffullpath="$fpath$fname";
print $ffullpath,"\n";
if (-e $ffullpath )
    { symlink($ffullpath,$fname); };

opendir(DIR,".");
foreach $file (readdir(DIR))
    { print "$file \n"; }
close(DIR);

chdir("/tmp/")
Get text files with .pl extension:
while (<*.pl>)
    { push @files, $_; }
Reading text files into array.
opendir DIR, ".";
while ($file= readdir DIR)
{
    if (-T $file)
        { push @files, $file; }
};
@a1 = grep /.pl/, @files;

sub print_names
{
    my $i;
    print "names: ";
    foreach $i (@names)
        { print "$i "; }
    print "\n";
}
Call by &print_names;.
@names=("Muriel","Gavin","Susanne","Sarah","Anna","Paul"); print "The 3rd is $nambes[2] \n";
print "@names"; -elements separated by space.
$#names -index to last element in array.
scalar(@names) - length
Pushing to end push @names, "Chelton";
Pushing to front unshift @names, "Frank";
Poping frontshift @names;
Poping and getting back my $temp=pop @names;
splice @names,1,3; cuts from pos 1, 3 elements.
udef $names kills the variable.

my @cities=("Melbourne","New York", "Tokyo", "Paris");
my $t1=join ":", @cities;
Melbourne:New York:Tokyo:Paris
my @t2=split /:/, $t1;
Melbourne New York Tokyo Paris

Comparison Operators:
For string use operators, for numeric use letters.
{eq,ne,gt,lt,ge,le}
{==,!=,>,<,>=,<=}

if [ "$result" == "1" ]; then return 1; fi
chop($name=<STDIN>); -also grabs return so its chopped.
chomp($name=<STDIN>); - only remove last character if return.

Here is an example of writing a function in Perl. A list is passed in by reference and a string by value.

# Read a file to a list routine.
# Read a file to a list routine.
# Example
#
# @mynames=();
# fill_list2(\@mynames,"temp00.txt");
#
sub fill_list2
{
    my ($names, $file) = @_;
    open STUFF, $file or die "error: could not open $file\n";
    while (<STUFF>)
        { push @$names, $_; }
};