Introduction to Linux Scripting (Part 2): Advanced Scripting

23
Introduction to Linux Scripting (Part 2): Advanced Scripting Brett Milash and Wim Cardoen CHPC User Services

Transcript of Introduction to Linux Scripting (Part 2): Advanced Scripting

Page 1: Introduction to Linux Scripting (Part 2): Advanced Scripting

Introduction to Linux Scripting (Part 2):

Advanced ScriptingBrett Milash and Wim Cardoen

CHPC User Services

Page 2: Introduction to Linux Scripting (Part 2): Advanced Scripting

Getting the exercise files

• For today’s exercises, open a session to linuxclass.chpc.utah.edu or one of the cluster head nodes and run the following commands:

cp ~u0424091/LinuxScripting2.tar.gz .tar xvfz LinuxScripting2.tar.gzcd LinuxScripting2/

Page 3: Introduction to Linux Scripting (Part 2): Advanced Scripting

Capturing output of a command

• The output of a command can be put directly into a variable with the backtick: `

• The backtick is not the same as a single quote:

` '• Bash form: VAR=`wc -l $FILENAME`• Tcsh form: set VAR="`wc -l $FILENAME`"

Page 4: Introduction to Linux Scripting (Part 2): Advanced Scripting

Dates and Times

• Date strings are easy to generate in Linux

– “date” command gives the date, but not nicely

formatted for filenames

– “date --help” or “man date” will show format options

• A nice formatted string format (ns resolution):

$ date "+%Y-%m-%d_%k-%M-%S_%N"2018-09-18_10-08-57_791967522

• You can put other things in the format string:

$ date "+Today is %A %m-%d-%Y”Today is Tuesday 09-18-2018

Page 5: Introduction to Linux Scripting (Part 2): Advanced Scripting

Exercise 2.1

Modify your previous script so that instead of writing to an

output file with a fixed name, the output filename is derived

from the input file (e.g., ‘filename” becomes “filename.date”).

Don’t forget to copy your script in case you make a mistake!

Command execution to string - VAR=`command` (use the

backtick)

Dates - date “+%Y-%m-%d_%k-%M-%S_%N” (or pick your own

format)

Page 6: Introduction to Linux Scripting (Part 2): Advanced Scripting

Solution to Exercise 2.1#!/bin/bashINPUT=$1DATE=`date +%Y-%m-%d_%k-%M-%S_%N`OUT=”$INPUT.$DATE”grep ‘\!’ $INPUT > $OUTwc -l $OUT

#!/bin/tcshset INPUT = $1set DATE = "`date +%Y-%m-%d_%k-%M-%S_%N`"set OUT = “$INPUT.$DATE”grep ‘\!’ $INPUT > $OUTwc -l $OUT

Every time you run the script, a new unique output file should have been generated.

Page 7: Introduction to Linux Scripting (Part 2): Advanced Scripting

If statements#!/bin/bashVAR1="name"VAR2="notname”dirname=“.”if [ $VAR1 == $VAR2 ] thenecho ”VAR1 and VAR2 are equal"

elseecho ”VAR1 and VAR2 not equal"

fiif [ -d $dirname ]thenecho ”$dirname is a directory!”

fi

#!/bin/tcshset VAR1 = "name"set VAR2 = "notname”set dirname = “.”if ($VAR1 == $VAR2) thenecho ”VAR1 and VAR2 are equal"

elseecho ”VAR1 and VAR2 not equal"

endifif ( -d $dirname ) thenecho ”$dirname is a directory!"

endif

• The operators ==, !=, &&, ||, <, > and a few others work.• You can use if statements to test two strings, or test file

properties.• See the manual page on “test”

Page 8: Introduction to Linux Scripting (Part 2): Advanced Scripting

Testable file propertiesTest bash tcsh

Is a directory -d -d

If file exists -a,-e -eIs a regular file (like .txt) -f -f

Readable -r -r

Writeable -w -w

Executable -x -x

Is owned by user -O -oIs owned by group -G -g

Is a symbolic link -h, -L -l

If the string given is zero length -z -z

If the string is length is non-zero -n -s

-The last two flags are useful for determining if an environment variable exists. -The rwx flags only apply to the user who is running the test.

Page 9: Introduction to Linux Scripting (Part 2): Advanced Scripting

Loops (for/foreach statements)#!/bin/bashfor i in 1 2 3 4 5 do

echo $idone

for fname in *.cdo

grep "string" $fname >> outdone

#!/bin/tcshforeach i (1 2 3 4 5)

echo $iend

foreach fname (*.c)grep “string” $fname >> out

done

• Loops can be executed in a script --or-- on the command line.• All loops respond to the wildcard operators *,?,[a-z], and {1,2}• The output of a command can be used as a for loop input.

Page 10: Introduction to Linux Scripting (Part 2): Advanced Scripting

find command• ”find” searches a directory (and its subdirectories) for files

matching any number of conditions:• File name• File type• File permissions• And many, many others

• Find can print each file’s name:find $HOME -name “*.pdf” -printfind . -type d -print

• Or execute a command on the file• {} represents the file that was found• Command must end with “\;”find . -name “*.txt” -exec gzip {} \;

Page 11: Introduction to Linux Scripting (Part 2): Advanced Scripting

xargs command

• “xargs” reads values from the standard input, then executes some command on each of those valuesfind . -name “*.data” -print | xargs gzip

• Commands can be run in parallel - very useful on multi-core machines!# Find .data files, run analyses 5 at a time:find . -name “*.data” -print | xargs -P 5 run_analysis

Page 12: Introduction to Linux Scripting (Part 2): Advanced Scripting

Exercise 2.2Congratulations! You’ve inherited files from a very messy project. You need to write a script to clean it up. In LinuxScripting2/ex2.2, create a script to organize the files in the MessyProject directory. Your script needs to do the following:1. Create directories “executables”, “source_code”, documentation”, and

“data”2. Remove any object files (files whose names end with .o)3. Move any source code files (.c or .h files) to source_code4. Move any PDF files into “documentation”5. Move any regular files (not directories) that are executable into

“executables”6. Move any .txt files into “data”If you need to “reset” your directory, you can extract the files from messyproject.tar:

tar xvf messyproject.tar

Page 13: Introduction to Linux Scripting (Part 2): Advanced Scripting

top

• Shows interactive display of current processes on machine

• Interactive commands:• u (limit to a user)• f (sort by different columns)• H (toggle between threads/processes)• q (exit)

• Great for monitoring your usage

Page 14: Introduction to Linux Scripting (Part 2): Advanced Scripting

“Strict” Mode ( bash only )• Some bash settings simplify debugging:

set -e # Exit immediately on any errorset -u # Error if referencing undefined variableset -o pipefail # Error on any pipe command

# Example: this code should fail:pattern=“somestring $some_undefined_variable”grep $pattern non_existent_file | wc -l

• You can do this all at once:set -euo pipefail

• See Aaron Maxwell’s blog:– http://redsymbol.net/articles/unofficial-bash-strict-mode/

• Also helpful is “set -x”: prints each line before execution

Page 15: Introduction to Linux Scripting (Part 2): Advanced Scripting

Functions ( bash only )

• You can define functions in bash:function describe_file () {

fname=$1fsize=`cat $fname | wc -c`fowner=`ls -l $fname | cut -d' ' -f3`echo “File $fname owner: $fowner size $fsize bytes.”

}

describe_file messyproject.tar

File messyproject.tar owner: u0424091 size 20480 bytes.

Page 16: Introduction to Linux Scripting (Part 2): Advanced Scripting

Basic Arithmetic#!/bin/bash#initializationi=1#incrementi=$(( i++ )) #addition, subtractioni=$(( i + 2 - 1 ))#multiplication, divisioni=$(( i * 10 / 3 ))#modulusi=$(( i % 10 ))#not math, echo returns "i+1"i=i+1

#!/bin/tcsh#initialization@ i = 1#increment@ i++#addition, subtraction@ i = i + 2 - 1#multiplication, division@ i = i * 10 / 3 #modulus@ i = i % 10#not math, echo returns "i+1"set i="i+1"

• Bash uses $(( )), whereas tcsh uses @ • Important! This only works for integer math. If you need more,

use python.

Page 17: Introduction to Linux Scripting (Part 2): Advanced Scripting

sort

• Sorts the lines of a file (or its standard input)• Writes sorted lines to standard output• Takes many options:• -n – numeric source• -f – case insensitive• -c – check if files sorted

$ who | sortu0424091 pts/13 2019-06-18 10:07 (brett15.chpc.utah.edu)u0564870 pts/0 2019-06-17 16:09 (:101)u0564870 pts/12 2019-06-17 16:24 (:111)u0564870 pts/5 2019-06-17 16:22 (:104)u0840590 pts/15 2019-06-11 13:23 (:114)

Page 18: Introduction to Linux Scripting (Part 2): Advanced Scripting

wget: retrieve from a URL

• Given a URL, wget retrieves the web page into a file

• Local file name is the basename of the URL• Very verbose! Can be quieted with “- - quiet”• Very useful for retrieving data files, source

code from github, etc.

Page 19: Introduction to Linux Scripting (Part 2): Advanced Scripting

Manipulate paths: basename and dirname

• basename and dirname help you manipulate long path names

• basename returns the last part of a long path• dirname returns everything before the basename• Typically used within backticks

• Also works with URLs

$ basename /uufs/chpc.utah.edu/common/home/u0424091/LinuxScripting2LinuxScripting2$ dirname /uufs/chpc.utah.edu/common/home/u0424091/LinuxScripting2/uufs/chpc.utah.edu/common/home/u0424091

Page 20: Introduction to Linux Scripting (Part 2): Advanced Scripting

Comparing files: comm and diff• diff provides a line-by line comparison:

• comm compares two sorted files side-by-side:$ comm dessert_toppings floor_waxes

BeeswaxCaramel

CarnaubaChocolate

JohnsonNew Shimmer

NutellaWhipped Cream

$ diff hello_world1.c hello_world2.c1a2> #include <math.h>5c6< printf("Hello, world!\n");---> printf("The value of pi is %f.\n", M_PI );

Page 21: Introduction to Linux Scripting (Part 2): Advanced Scripting

Test the success/failure of a command

• Every linux command terminates with an exit code: 0 == success, not 0 == error

• The shell variable “$?” holds the exit code of the last commanddiff hello_world1.c hello_world2.c > differencesif [ $? == 0 ]then

echo "files are the same"else

echo "files are different"> fi

Page 22: Introduction to Linux Scripting (Part 2): Advanced Scripting

Exercise 2.3

• In LinuxScripting2/ex2.3 you’ll find a file of URLs. Write a script that retrieves each of those URLs into a file and checks if the content has changed since the last time you ran the script.

Page 23: Introduction to Linux Scripting (Part 2): Advanced Scripting

Questions?

Email [email protected]@[email protected]