Szukaj na tym blogu

środa, 8 czerwca 2011

W systemach unix/linux w celu administracji systemem operacyjnym lub rozwijaniem jego funkcjonalności, wykorzystuje się kilku jezyków programowania :
- SHELL (bash, ksh, bourne, c shell itp)
- C/C++
- PERL
- SHELL / AWK / SED

Zastosowanie tych jezyków jest następujące :
SHELL
   Jest to bardzo prosty język programowania pozbawiony wielu zaawansowanych struktur danych takich jak chociażby : tablica wielowymiarowa, zmienna liczbowa zmiennoprzecinkowa, brak zdefiniowanych funkcji, problemy z parsowaniem textu.
   Z uwagi na swoją prostotę i domyslną obecność we wszystkich odmianach unix-a/linux-a tuż po instalacji systemu, jest on wykorzystywany przez administratorów w celu automatyzacji czynności lub wyciagania informacji z systemu.

C/C++
   Jest to obiektowy C++ i nieobiektowy C jezyk programowania. Jeden z najcięższych w jakich programuje człowiek.
   Jeżeli chodzi o ich zastosowanie to w językach tych :
- pisze się sterowniki
- tworzy systemy operacyjne
- tworzy aplikacje użytkowe pod platforme np. unix/linux
- mechanizmy zarządzania pamięcia w unix/linux np. semafory, kolejki, pamięc współdzielona

PERL
   Język, który jest obency w każdej implementacji systemu unix/linux. Posiada rozbudowaną semantykę znaczników do wspołpracy z textem. Ma zdefiniowane wiele funkcji z których można skorzystać bez konieczności manualnego ich oprogramowywania.
   Idealny jezyk do parsowania textu.

SHELL / AWK / SED
   Połączenie tych 3 jezyków programowania pozwala administratorowi na zastąpienie umiejetności parsowania textu przez PERl-a.

   Celem tego tutorial-u jest omówienie podstawowych zagadnień związanych z programowaniem w języku SHELL i jego odmianą o nazwie Korn Shell (ksh) wykorzystywaną np. w Solaris10.
   Można go również używać pod innymi platformami unix/linux ale może wymagać doinstalowania, w solaris10 jest natywnie obency po instalacji oesa.
W systemie Solaris10 mamy do dyspozycji 3 podstawowe shell-e :
- Bourne Shell
- C Shell
- Korn Shell

Bourne Shell
Oryginalny UNIX shell i jest domyślny dla root użytkownika. Domyślny znak zachęty dla użytkownika zwykłego to $ natomiast dla root znak ten to #

C Shell
Posiada szereg funkcji, których Bourne Shell nie posiada : historia komend, aliasy kontrola job-ów. Domyślny znak zachęty dla użytkownika zwykłego to hostname% natomiast dla root znak ten to hostname#

Korn Shell
Łączy w sobie funkcjonalność Bourne + C SHell. Domyślny znak zachęty dla użytkownika zwykłego to $ natomiast dla root znak ten to #

Solaris 10 posiada trzy dodatkowe alternatywne SHell-e :
- Bash
- Z Shell
- TC Shell



Poniżej znajduje się omówienie semantyki programowania w języku Korn SHell :


Arrays

#!/bin/ksh
#Arrays.ksh

# Introducing arrays: a group of similar variables.
# A god use ofr an array would be an array to hold
# a list of groceries of the months of a year.
#
# - Jim

# To create an array:
# ArrayName[ElementNumber]="Value"

# Defining a counter:
index=7

# Example
Child[0]="Tom"
Child[1]="Kate"
Child[7]="Colleen"

# Example of not using index 0.
Month[1]="January"; Month[2]="February"
Month[3]="March"; Month[4]="April"
Month[5]="May"; Month[6]="June"
Month[7]="July"; Month[8]="August"
Month[9]="September"; Month[10]="October"
Month[11]="November"; Month[12]="December"


# Printing a variable:
print "index is $index"

# Can not access an array element by $Month[7]. Ksh auto interprets everything that goes after $sign as variable

# To access the value in an array element.
print "The fifth month is: ${Month[5]}"

# To print all values in an array:
print "The whole array is: ${Month[*]}"
#
#
exit


Basic Math

#!/bin/ksh

# Korn shell allows basic math: +, -, *, /,
# and % (remainder of the division).
# Korn shell only performs amth on integers.
# It will truncate 7.9 to 7 and 2.1 to 2.


# - Norbert 666-666-6666


#Define some variables:
x=5; print "x is: $x" #multiple cmds in one line by using ; sign
y=11; print "y is: $y"
z=18; print "z is: $z"

# To perform math, use double parentheses.
# However, no need to use $ in front of the variable.


(( Result = y + x ))
print "y + x is: $Result"


(( Result = z - y ))
print "z - y is: $Result"

(( Result = y / x ))
print "y / x is (Remember returns whole number): $Result"

(( Result = y % x ))
print "y % x is: (This is the remainder operation): $Result"

# Korn shell truncates numbers to make the integers.
(( Result = 1.9 + 1.9 + 1.9 ))
print "In Korn Shell, 1.9 + 1.9 + 1.9 is: $Result" # there are version of korn shell with decimal points

# Adjusting position within an array/list:
Position=1
Color[$Position]="Red"


(( Position = Position + 1 ))
Color[$Position]="Orange"


print "The contents of the array \"Color\" are: ${Color[*]}" # add second "" inside of ""


# To print just a -5 use -R.
print -R "-5" #if not used with -R, it will tell shell to treat "-5" as -5 flag


exit

Case Statement 1

#!/bin/ksh

# NonCase.ksh

# Reviews if-elif-else construct.

# - jakubn

# If you want to test 1
# variable for several
# conditions, you can use
# if-elif-else construct


# if (( test1 ));then
# command group 1
# elif (( test2 )); then
# command group 2
# elif (( test3 )); then
# command group 3
# else
# command group 4
# fi




# Remember the FIRST test that
# is true gets executed. After,
# the program automatically
# breaks out of the if-elif
# structure, and does not perform
# any more tests.



print
print "Please enter the type of "
print "backup you want done:[ABC]."

print "A: Daily"
print "B: Weekly"
print "C: Quarterly:
print "D: Special"

print

print -n "Response: "
read Response

print



if [[ $Response = [Aa] ]]
then

# Do a Daily backup
print "Starting daily backup."
# /#oracle/backup.daily.ksh

elif [[ $Response = [Bb] ]]
then
# Do a Weekly backup
print "Starting weekly bakup."
# /oracle/backup.weekly.ksh

elif [[ $Response = [Cc] ]]

# Do a Quartlerly backup
print "Starting quarterly backup."
# /oracle/backup.quarterly.ksh

elif [[ $Response = [Dd] ]]
then

# Do a Special backup
print "Starting daily backup."
# /oracle/backup.daily.ksh

print
print "Please take out daily tapes."
print "Please put in weekly tapes,"
print -n "and hit 'enter' to continue." #gives you time to get tapes

read Waiting

print
print "Starting weekly backup."
# /oracle/backup.weekly.ksh


else

# Person entered in bad data.
# Tell them to enter a right
# choice

print "'$Response' is not a valid choice."
fi
#
#
exit


Case Statement 2

#!/bin/ksh

# Case.ksh

# Introduces the case statement
# which allows you to test 1
# variable against several
# different values. The 1st test
# that is true will result in
# the code assigned to it to be
# executed until a ;; is found



# After, it breaks out of the case statement
# without performing any more tests


# You need to end code with
# ;; before the next pattern
# matching test. No fall through
# allowed.


# Format of case statement:

# case $Var in
# Pat1)
# Code 1 ;;
# Pat2)
# Code 2 ;;
# Pat3)
# Code 3 ;;
# *)
# Default Code ;;
# esac


print -n "Enter a value: "
read Var

# To read in to a var., don't
# use $ sign. To get info out,
# use $ sign.


case $Var in
# comment
1) print "value is 1";;
2) print "value is 2";;
3|71) print "value is 3 or 71";;
*) print "Please enter 1, 2, 3, or 71";;
esac


print
print "Please enter the type of "
print "backup you want done:[ABCD]."


print "A: Daily"
print "B: Weekly"
print "C: Quarterly"
print "D: Special"

print

print -n "Response: "
read Response

print



case $Response in
[Aa])
# Do a Daily backup
print "Starting daily backup."
# /oracle/backup.daily.ksh
;;


@(B|b)) #requirement of 1 of whatever it is in ()
# Do a Weekly backup
print "Starting weekly backup."
# /oracle/backup.weekly.ksh
;;

[Cc])
# Do a quarterly backup
print "Starting quarterly backup."
# /oracle/backup.quarterly.ksh
;;

[Dd])
# Do a special backup
print "Starting daily backup."
# /oracle/backup.daily.ksh

print
print "Please take out daily tapes."
print "Please put in weekly tapes,"
print -n "and hit 'enter' to continue." #gives you time to get tapes

read Waiting

print
print "Starting weekly backup."
# /oracle/backup.weekly.ksh
;;

*)
# Person entered in bad data.
# Tell them to enter a right
# choice

print "'$Response' is not a valid choice."
;;
esac


Debugging 1

#!/bin/ksh

# Debugging1.ksh
# This script introduces debugging
# using "#!/bin/ksh -x" or
# set -x (and set +x).

# Also, it reminds you how useful
# print statements can be.

# - jakubn 666-666-6666

# Turn on debugging. # you can put multiple set -x and set +x statements in your script
set -x
y="Monday"

print "Save the cheerleader, save the world."

# Turn off debugging.
set +x

#print statement for debugging
print "After cheerleader statemetn, the value of y is: $y"

#The following print statement won't work
# because it has an extra "t" in the word print.
printt "This is an invalid print statement."


Debugging 2

#!/bin/ksh -x

# Debugging2.ksh ---> puts whole code in debugging mode ksh -x
# This script introduces debugging
# using "#!/bin/ksh -x" or
# set -x (and set +x).

# Also, it reminds you how useful
# print statements can be.

# - jakubn 666-666-6666


y="Monday"

print "Save the cheerleader, save the world."


#print statement for debugging
print "After cheerleader statemetn, the value of y is: $y"

#The following print statement won't work
# because it has an extra "t" in the word print.
printt "This is an invalid print statement."

exit


Else If Statement 1

Przetwarzanie bloku kodu "if else" wygląda następująco.


#!/bin/ksh

# elif.ksh

# This program demonstrates the use
# of elif, the ability to make a
# 2nd test if the 1st if false.

# - Jim

# Assign a default grade.
Grade="F"

#Clear the screen.
clear #This is unix command.

print -n "Enter number grade: "
read NumberGrade

if (( NumberGrade > 89 )); then

#Person gets an "A".
Grade="A"

elif (( NumberGrade > 79 )); then

#Person
Grade="B"

elif (( NumberGrade > 69 )); then

#Person
Grade="C"

elif (( NumberGrade > 59 )); then

#Person
Grade="D"

fi

print
print "Letter grade is: $Grade"

exit


Else If Statement 2

#!/bin/ksh

# elif2.ksh

# This program demonstrates the use of else at the end of an elif statement

# - Jim

# Let's buy a bus ticket.
# The price may change
# depending on the age of the apssenger.


print -n "Enter your age: "
read Age

if (( Age < 5 )); then #The Cost if free TicketCost="Free" elif (( Age > 54 )); then

#Senior citizens get
#1/2 price.
TicketCost="\$1" #it means 1 dollar, so it string 1$ dollar sign

else

#Normal price.
TicketCost="\$2"

fi

print
print "Cost is: $TicketCost"


exit


If Statement with Math Operations 1

#!/bin/ksh

# IfMath1.ksh

# This program introduces the "if" statement.

# - Jim

# prompt the user to enter a number.
print -n "Enter your age: "
read Age

# Create an if statement.

if (( Age >= 18 )) #don't put comments between if and then keywords
then #double (( means math, we can also do math comparisons apart of +,- etc
print "Vote!" #you can't create (( 18 >= Age, number must be on right side
fi

# Math tests: #you can do var to var or var to nr not nr to var
#
# (( Num1 == Num2 )) Note: == not =
# (( Num1 != Num2 ))
# (( Num1 < Num2 )) # (( Num1 > Num2 ))
# (( Num1 >= Num2 ))
# (( Num1 <= Num2 )) exit If Statement with Math Operations 2

#!/bin/ksh


# IfMath2.ksh

# This program introduces multiple tests
# ( AND => "&&" and OR => "||" )
# inside of an "if" statement.

# - Jim

# prompt the user to enter a number.
print -n "Enter your age: "
read Age

print

print -n "Enter the number of children you have: "
read NumberOfChildren

if ( (( Age < 30 )) && ((NumberOfChildren == 0 )) ); then #you don't need () single paratheses here # Note the use of == and not = print "Single and loving it!" fi if ( (( Age >= 30 )) || (( NumberOfChildren > 0 )) ); then

print "Bummer!"
print "Things could be worse. You could be a Cube fan."

fi

exit


If Statement with String Operations

#!/bin/ksh

#IfStrings.ksh

#Goes over testing strings
#instead of match. Also, it
#introduces pattern matching.

# - Norbert

# Here are math tests and the
# corresponding string tests:
# (Notice the square brackets
# and the double quotes.)
# Also, you need white space
# between [[ and var name.
#
# Equals:
# (( num1 == num2 )) #we didn't use $ operator cause Korn Shell knows that everything that is in (( is a variable
# [[ "$s1" = "$s2" ]] #if want test string vs string or string vs value; "$s1" --> variable s1
#
# To assign:
# s1=$s2 #s2="New York City" must use "" cause white space between words ksh interpr as 3 different vars
# #you use double quotes "" in case the value in var has spaces in it!
#
# Not equals:
# (( num1 != num2 ))
# [[ "$s1" != "$s2" ]]
#
#
# Less then:
# Before:
# (( num1 < num2 )) # [[ "$s1" < "$s2" ]] # # Note: This is based off of the # ASCII character set. # Therefore "Z" is before "a". # Also, in ASCII 19 is before 2. #cause it compares 1 against 2 then 19 against 2 # # # Greater than: # After: # (( num1 > num2 ))
# [[ "$s1" > "$s2" ]]
#
#
# Less than or equal to:
# (( num1 <= num2 )) # ( [[ "$s1" < "$s2" ]] || [[ "$s1" = "$s2" ]] ) # # Greater then or equal to: # (( num1 >= num2 ))
# ( [[ "$s1" > "$s2" ]] || [[ "$s1" = "$s2" ]] )
#
#
# Zero length:
# [[ -z "$s1" ]]
#
# Nonzero length:
# [[ -n "$s1" ]]
#
#
#
exit


Loop Break & Continue Statements

#!/bin/ksh
#
# break -> statement means to stop the loop
# if you are in the middle of do and done
# it will bring to the end of the loop write where after done is
#
#
# continue -> if you are in the middle of the cmd's
# and you decide that you don't want to execute all
# of the cmd's after it, it will move you back to the top of your # loop
# and start executing from there, it bypasses that are after it
#
#


# it is best to not use break or continue statements

# example1
for Var in 1 2 3 5 6 7 8
do
if (( Var == 3 ))
then
continue
fi

print "\$Var is $Var"


if (( Var == 6 ))
then
print "At 6; breaking!"
break
fi

done

print "Outside of for loop"



# example2 - multilevel breaking

# while test; do

# while test; do
# continue 2 #continue from outer loop(2lev loop)
# done
# done


# while test; do
# while test; do
# break 2 #break to outer loop level 2
# done
# done

print


Loop For

# In a list, when Korn shell sees
# a white space (space, a tab, or a
# ), it considers that the
# boundary for a list entry.



# for Flower in rose Water Lily sunflower # got four entries
# for Flower in rose "Water Lily" sunflower # got three entries


# n=0
# while (( n < 6 )) # do # cube n # print cube # increment n by 1 # done # the same as in while above by using for loop for n in 0 1 2 3 4 5 do (( Cube = n * n * n )) print "$n cubed is $Cube." done print print -n "Waiting. Hit "
read Waiting


print
print "The shells you can use are: "
print



for Shell in $(grep / /etc/shells) # $() -> whatever is inside do #() is unix cmd
print "\t$Shell" # \ -> means add to or remove from
done # meaning of the next character
# \t -> means indent tab
print

Loop Until

# while (test) # this test was true, do cmd's below
# do
# commands
# done


# until (test) # if test is false, then do cmd's below
# do
# commands
# done


# basically, the until loop
# is the opposite of the
# while loop.

# while loop runs a
# test. if the test is
# true, then the code
# inside of do to done
# is repeatedly executed
# until the test is false.


# "while (test)" is the same
# as "until ! (test)". And,
# "while ! (test)" is the same
# as "until (test)".


# "while not true" is the same as "until true".
# And "while true" is the same as "until not true"
#
# it means basically this :
# run code between do and done until (test) is false
# while (true)
# until (false)


# Make sure that you have the
# space between the ! and the test.


# Structure:
# until test
# do
# cmd's
# done



print "until with !."

n=0

# while (( n < 6 )); do until ! (( n < 6 )); do (( Cube = n * n * n )) print "$n cubed is $Cube." (( n = n + 1 )) done print print -n "Waiting. Hit ."
read Waiting
print
print "until without !."

n=0


until (( n>=6 )); do

(( Cube = n * n * n ))
print "$n cubed is $Cube."

(( n = n + 1 ))
done

Loop While

#!/bin/ksh


# while loop runs a
# test. if the test is
# true, then the code
# inside of do to done
# is repeatedly executed
# until the test is false


# if test
# then
# commands
# fi


# structure:
# while test
# do
# commands
# done

n=0

while (( n < 6 )); do (( Cube = n * n * n )) print "$n cubed is $Cube." # n do szescianu (( n = n+1 )) done while [[ -a /tmp/a.txt ]] #a -> any type of file, does this file exist
do
sleep 2 #unix cmd, means pause for 2 seconds
done

print "/tmp/a.txt is gone."




# we might e.g. check with df cmd whether ceratain fs is
# less then 85 %, as logn at it is we can wait e.g. for 10 seconds
# and perform another the same test and so on.
# that's how we use while with sleep cmd


More Pattern Matching

#!/bin/ksh

print -n "Enter yes or no: "
read Answear
#
#
#
if [[ "$Answear" = [yY]* ]]
then

# Matches "y*" or "Y*".
# Also works for more than 2
# characters. For example:
# [aeiouAEIOU]

print "Matched y* or Y*"
fi
#
print -n "Enter 1st word: "
read Answear
#
#
#
if [[ "$Answear" = [0-9]* ]]
then

# A range [0-9]
print "This is not a word."
fi
#
#
if [[ "$Answear" = [2-4]* ]]
then

# Smaller range.
print "Starts a 2, 3, or 4."
fi
#
#
if [[ "$Answear" = [13579]* ]]
then

# Odd number answear
print "Starts w/ an odd number."
fi




print -n "enter 2nd word: "
read Word


if [[ "$Word" = [a-zA-Z][a-zA-Z][a-zA-Z]* ]]
then

# Is a word of at least 3 characters.
print "Is a word of at least 3 chars."
fi



print -n "Enter 3rd word: "
read Answear

if [[ "#Answear" = [!a-z]* ]] # ! ---> means opposite is true e.g. Upper Case Letters and Numbers and other signs
then

print "Sth"

fi

exit


Pattern Matching 1

#!/bin/ksh

print -n "Enter a username: "
read UserName

if [[ "$UserName" = "bob" ]]
then

# match "bob".
# does not match "b0b", nor "Bob".

print "Matched \"bob\""
fi

if [[ "$FileName" = oracle??? ]] # without "" cause if with this, shell will interprete this as oracle???
then

# matches oracle followed
# by any 3 characters.

print "Matched \"oracle???\""
fi

if [[ "$FileName" = a* ]]; then

# matches: "a" followed by
# anything or nothing.

print "Matched \"a\" followed by"
print "anything or nothing."
fi

if [[ "$FileName" = "a*" ]]; then

# Matches "a*" only.
print
print "Matched \"a*\" only."
fi

exit


Pattern Matching 2

#!/bin/ksh

print -n "Enter a name: "
read Name

# ?() matches 0 or 1 of what
# is in the ().
# ? (pat)
# ? (pat1|pat2|pat3)

if [[ $Name = tom?(my) ]]
then
# tom, tommy
print "Hi Tom"
fi


if [[ $Name = [jJ]ohn?(ny|boy|nie) ]]
then

# [jJ]ohn, [jJ]ohnny,
# [jJ]ohnboy, [jJ]ohnnie
print "Hi John"
fi



if [[ $Name = ann?([ae]) ]]
then
# ann, anna, anne
print "Welcome Ann"
fi
exit


Pattern Matching 3

#!/bin/ksh

# ?(optional patterns) String
# String? (optional patterns)
# String? (optional patterns) String2
# String? (pat1|pat2|pat3)
#
# @() matches exactly 1 of what
# is in the ().
# @ (pat1|pat2|pat3)
# Useful for looking for a list
# of things




if [[ $Name = T@(homas|om|ommy) ]]
then
# Tom, Thomas, Tommy
print "Hi Tom"

fi




if [[ $Name = [jJ]ohn@(|ny|boy|nie) ]] # notice (|ny....) means that john is ok
then
# [jJ]ohn, [jJ]ohnny,
# [jJ]ohnboy, [jJ]ohnnie
print "Hi John"
fi

print -n "Enter a color: "
read Color




if [[ $Color = @(white|lemon|sky blue) ]]
then
# Nice colors.
print "relaxing color"

fi





if [[ $Name = ch@(|ap?(t)|apter)01.txt ]]
then
# ch01.txt, chap01.txt
# chapt01.txt, chapter01.txt
print "Found chapter01"
fi

exit


Pattern Matching 4

#!/bin/ksh

#
# @(req. patterns)String
# String@(req. patterns)
# String@(req. patterns)String2
# String@(pat1|pat2|pat3)
#
# *() matches 0 or more of what is
# in the () in any combination.
# *(pat1|pat2|pat3)
#

if [[ $Name = T*(homas|om|ommy) ]]
then
# T
# Tom, Thomas, Tommy
# Tomommy, Tommyhomas
# Tomommyommyom
print "Hi Tom"

fi

print -n "Enter an answear: "
read Answer

if [[ Answer = [Aa]*([a-z]) ]]
then

# Won't match "don't".
# Starts with a letter a or A.
print "Starts with a or A."
fi

# +(req pats) => matches one
# or more of the req. patterns.
# +([a-z]) => chars only
# + ([0-9]) => numbers only
# above matches 0008, 91, 0.

if [[ $Answer = +([a-z]\'+([a-z]) # if sbd type word don't
then

# could be a contracted would.
print "contraction."
fi

# !(excluded patterns) =>
# matches anything but what
# is in ()
# Think of it as * - excluded
# patterns.

# Examples:

read User

if [[ $User = !(root) ]]
then

# Anybody but root.
print "Anybody but root."
fi



read File
if [[ $File = Ora_!(jan|feb).txt ]]
then

# matches Ora_mar.txt, Ora_.txt
# doesn't march:
# Ora_feb.txt, Ora_jan.txt
# Found file
print "Found File!"
fi
exit


Reading Input

#!/bin/ksh

#ReadingInput.ksh
#
# This script shows how to read input
# from the user. Moreover, it warns you
# about how whitespace is used to
# input more then one variable.

# jakubn 666-666-6666

#Printing with the .
print "Please enter a city name: "

#print a blank line
print

#Printing without the .
print -n "Please enter a city name: " #cursor didn't go to the next line, means carriage return

#Read in value: #read statement auto assumes when you type space within string as a end of variable
read City

print "The name of the city is: $City" #assign info to variable doesn't need $ sign, when getting info from var you need $ sign
print

#####
# Problems with white spaces:
print -n "Please enter the names of 2 cities: " #if you type New York Trenton, read will set New as City1 and York

Trenton as City2


#You can read in multiple values at once. #it is best to read one var at a time
read City1 City2

print "The name of the FIRST city is: $City1"
print "The name of the SECOND city is: $City2"

exit


Tests On Files

# Does the file exist?

if [[ -a /etc/passwd ]] #[] string test
then

print "passwd file exists."
print

fi

#
# Think of "a" as any
# type of file.


# ===


# Is it a regular file?
# Is it a file that has
# regular data?


if [[ -f /bin/ksh ]] #-f means file
then

# has text or is
# executable
print "ksh is Regular file"
print
fi




if [[ -d /etc ]] #-d means directory
then

print "Good. /etc exists."
fi







# Is it a shortcut?
# Is it a symbolic link?



if [[ -L /etc/aliases ]] #-L means symbolic link
then

ls -l /etc/aliases
print
fi


# Does the file have a size
# to it?

# if [[ -s file ]] #does a file has size or data in it, if file exist but is empty, this test is faulse
# -s for size



# Empty file or zero size:
if [[ ! (-s /tmp/a.txt) ]] #() is optional
then

print "/tmp/a.txt is empty."
fi



# Can YOU read the file?
# [[ -r file ]]
# if dir, then you can
# do an ls on dir
# but not ls -l

# Can YOU write to the file?
# [[ -w file ]]
# if dir, then you can
# write to that dir if
# you can also execute.



# can YOU execute the file?
# [[ -x file ]]
# if dir, then you can
# execute files in the dir
# and execute (rm, cd, ls -l)
# for that dir


# Are you the owner of the file?
# [[ -O file ]]


# Is your primary group the
# owner of the file?
# [[ -G file ]]


# [[ f1 -nt f2 ]]
# f1 is newer than f2


# [[ f1 -ot f2 ]]
# f1 is older than f2.