Thursday, October 1, 2020

Automatically Login to Windows 10 without a password

As of the release May 2020 build of windows methodology:


WINDOWS + I  (settings)

turn OFF "Require Windows Hello sign-in for Microsoft accounts"

close the settings window (changes are saved automatically)


launch a CMD prompt AS administrator

run   " netplwiz "

You should now get a "USER ACCOUNT" window

UNselect the option "Users must enter user name and password...."  (the change above in the accounts makes this option visible)


You'll be asked to give a user name and password.  

Put in the username and  password for the main account for this machine

Press APPLY 


Sunday, September 20, 2020

Allow an OBS session to automatically control a second OBS

Had a situation where an OBS broadcast to YouTube with three OBS scenes, each with a different camera on a guest in our studio.  Along with the video cameras, OBS was displaying a PowerPoint presentations from a local computer, but also had occasions when users, via a ZOOM, needed to share their screen.

The product to YouTube is perfect, with presenters videos being shown on the screen, but since I had ZOOM users, I wanted their experience to be a familiar normal ZOOM meeting, with my 3 webthat they are used to, the web camera views showing my cameras along with all the other viewers who had cameras running.  I also wanted the screen share in ZOOM to be the same experience in zoom.  Meaning, I didn't want to share my cameras and presentation as one single share, the one that viewers on YouTube would see. 

So what I wanted was to have my 3 cameras (each on a different panel guest) being sent to ZOOM as a webcam automatically as I selected each of the 3 scenes, but just the webcam feed only, not any of the powerpoint or text or anything else.  And I needed it to happen automatically as I switched scenes.

SOOOO to solve it this way
tl; dr;
I set up 2nd computer and OBS instance with dedicated NDI feeds from each camera being send to the 2nd OBS.  Then used a remote control OBS app, a script in the 1st OBS that, upon selecting scenes would send a command to the 2nd OBS instance to switch to the matching scene that just had the dedicated feed of the appropriate camera.


Then on the FIRST OBS computer I installed this command line application.  It will allow you to send CLI commands to another OBS that is running WebSockets (remote control OBS app)

This allows you to change scenes on the remote computer using the command line.  The CMD sequence would look something like this to change scenes

OBSCommand.exe /server= /scene="SCENE_VALUE"


The NDI app for OBS was installed on BOTH computers.

On the first computer, each camera angle had its own separate NDI session that the the second OBS computer would receive.  This was configured in the EFFECTS FILTER on the primary OBS.


A script app was installed on the 1st OBS computer activates a script every time a certain scene was activated on the first BOS computer.  This calls the command line above to send a request to the second OBS computer

C:\Users\NAME\Downloads\OBSCommand_v1.5.3.+fixed_websocket\OBSCommand\OBSCommand.exe /server= /scene="SCENE_VALUE"

This command tells the remote system to change to "SCENE_VALUE" which is assigned in the variable in the script app.  So in the above example, "1" is the name of a scene on the second OBS computer, and "Safety" is the name of the other.

I setup a second computer running OBS.  And I installed "WEBSOCKETS" on it.  This program lets you control OBS from another device 


When I click on SCENE 1 on the First OBS computer, which has Camera 1 (+ data going to YouTube), it sends a command to the SECOND OBS computer to switch to its "Scene 1"...which contains ONLY the NDI feed of Camera 1 from the first OBS computer.

Make sense?  yea... i know.

THEN the second OBS computer output is saved as a webcam feed and goes to ZOOM.

I know craziness  but it works.

THEN on the SECOND computer you install the "VIRTUAL WEBCAM" output add on for OBS.  This will set the output of this OBS as a webcam that ZOOM will recognize as an input.

On my particular instance, my second OBS was running on a ZOOM ROOM computer

Make PowerPoint control other applications using VBA

Here's some code that will let you use PowerPoint to run .BAT files 

The basis of this code comes from Michael Kordahi's original post on his Linkedin account and OBS scripts page.  I found this very helpful and wanted to post how to do it, plus possible improvements.  I'm using it to control scenes in PowerPoint, but I've modified the code to use websockets.

Original post:

And Linkedin Post of an example:

I've modified Michael's code slightly from above, as I want it to call a .BAT. (his sent CTRL+ hotkey commands which also worked, but I needed to run power point from a different computer so i needed change it slightly)

In my case, I'm running PowerPoint, and as I advance slides, I want it to automatically send a command (via .BAT) to OBS Studio running on another computer, and I'm doing it in conjunction with WebSockets

So here is what happens.

As the slides advance, based on the FIRST line of text on the "Notes Description" on the PowerPoint slide, that will trigger the execution of a .BAT file.

This bat file sends a command to the computer running OBS to switch to a specific scene.

Diagram, PowerPoint has "OBS3" for a description.  Sends that to the OBS computer, which triggers a scene to automatically be displayed.

Now as I advance through PowerPoint, specific scenes will automatically occur.  I use this in a house of worship situation where I want to reduce the load of the worship team.

Here's how to make it work.

First install the WebSockets app on your OBS computer.  You'll also want to install it on PowerPoint computer (assuming they are different machines).  

A suggest program to also install is NOOBS  which will greatly aid in the creation of the .BAT script for you.


OBSCommand.exe /server= /password="password01" /scene="PowerPoint Full Screen (1)"

4> Create or load a PowerPoint presentation.



6> in "macro name" call it   OnSlideShowPageChange

Then click on "CREATE"

You'll see this:

Sub OnSlideShowPageChange()

End Sub

7> Make it look like this:

Sub OnSlideShowPageChange()
Dim i As Integer
Dim sNotes As String
Dim sKey As String

i = ActivePresentation.SlideShowWindow.View.CurrentShowPosition

s = Left(ActivePresentation.Slides(i).NotesPage.Shapes.Placeholders(2).TextFrame.TextRange.Text, 4)

If Left(s, 3) = "OBS" Then
sKey = Right(s, 1)
Shell ("CMD.EXE /c C:\OBSCommand\" & sKey & ".bat")

AppActivate ("PowerPoint")

End If
End Sub

8>  Please note the C:\OBSCommand\ should reflect the path that you are storing your BAT files in for this.

9> Now in your presentation "NOTES" put OBS1   or  OBS2   or   OBS3  on the first line.  This will correspond to the scenes.

In the example below, I have "OBS3" which, in the case of the example, the white screen on the left, when power point displays it, will call to run a bat file for "OBS3"

In this example, the script will check the first line for it to begin with OBS, then it will take the trailing number, which will be a "3"

10> now Launch NOOB

I've put in my server IP of my OBS box, I've put in the port and password.  Now click on the left most button "Not Connected" to imitate a connection

If successful, you should be able to now click on "SCENE" and then in the box next to "Switch To" you should be able to see all available scenes.

Once you have selected a scene, you can run "TEST COMMAND" and, if everything is configured, your scene should change in OBS.

Now export that command, and save it with a value of 1-9, in my example I saved it as "3"

10> Now start your PP presentation (F5) 

11> Make sure that OBS is running with your scenes, and change the slides in PowerPoint, you should see the images change in OBS

Thursday, July 23, 2020

OpenShot - Adding a title

You can add a title to OpenShot 

Using the Title Templates

Select "TITLE" at the top, pick a title template that you like. (or press CTRL+T )

Select a Title template that you want form the preset ones

Now you can edit the parameters.  For this document, we are going to focus on "FILENAME" and "LINE 1:"

Give it a FileName (this is stored in the OpenShot project file for future use should you save it)

Adjust the line number, in this case you can adjust "line 1" with the element you want.

Click on SAVE

Your title will now appear in the "Project Files" window

Click and drag that title to your timeline

Your video preview will show the title

By layering elements below the title, the title will overlay on those video elements


Open Shot - Speeding up editing playback

Speeding up OpenShot editing playback 

This is a common problem.  Playback video is stuttering, jerky, slow.
This is really due to the amount of processing the machine needs to do with video, especially if you are layering components like titles and effects.  Its not so much that your machine is slow, these codecs are just not perfect.

If you are suffering from this problem, the most effective way to reduce the 'editing' video quality level.  This won't affect the end product, it will just alter the way your video is rendered while you edit it.

Selecting the "Profile" button will bring up the profile list

Simply select a lower bit rate item in the PROFILE list.

This value is set to a very low setting, which, in many cases, will speed up the processing of videos.  Find one that works best for you.

When completed and ready to export the final product, change the profile back to its original setting.

Wednesday, June 10, 2020

Ford Super Duty 2003 Instrument Cluster Pin Outs

Ford Super Duty 2003 (early 04) Instrument cluster pin outs for some various versions in those time frames

Wednesday, April 15, 2020

Bash fundamentals

Bash scripting language

To create a bash script, you place #!/bin/bash at the top of the file.
Then, change the permissions on the file to make it executable:

 $ chmod u+x scriptname

To execute the script from the current directory, you can run ./scriptname and pass any parameters you wish.
When the shell executes a script, it finds the #!/path/to/interpreter.
It then runs the interpreter (in this case, /bin/bash) on the file itself.
The #! method is why many scripting languages use # for comments


# Use $1 to get the first argument:
echo $1


Comments in bash begin with # and run to the end of the line:

 echo Hello, World. # prints out "Hello, World."


Variables in bash have a dual nature as both arrays and variables.
To set a variable, use =:

foo=3  # sets foo to 3

But, be sure to avoid using spaces:

foo = 3 # error: invokes command `foo' with arguments `=' and `3'

If you want to use a space, you can dip into the expression sub-language that exists inside (( and )):

(( foo = 3 )) # Sets foo to 3.

To reference the value of a variable, use a dollar sign, $:

echo $foo ; # prints the value of foo to stdout

You can delete a variable with unset:

echo $foo    # prints 42
unset foo
echo $foo    # prints nothing

Of course, you can assign one variable to another:

foo=$bar # assigns the value of $bar to foo.

If you want to assign a value which contains spaces, be sure to quote it:

# wrong:
foo=x y z # sets foo to x; will try to execute y on z

# right:
foo="x y z" # sets foo to "x y z"

It is sometimes necessary to wrap a reference to a variable is braces:

echo ${foo} # prints $foo

This notation is necessary for variable operations and arrays.
There is no need to declare a variable as an array: every variable is an array.
You can start using any variable as an array:

foo[0]="first"  # sets the first element to "first"
foo[1]="second" # sets the second element to "second"

To reference an index, use the braces notation:

echo ${foo[1]}  # prints "two"

When you reference a variable, it is an implicit reference to the first index:

echo $foo       # prints "one"

You can also use parentheses to create an array:

foo=("a a a" "b b b" "c c c")
echo ${foo[2]}  # prints "c c c"
echo $foo       # prints "a a a"

To access all of the values in an array, use the special subscript @ or *:

array=(a b c)
echo $array       # prints a
echo ${array[@]}  # prints a b c
echo ${array[*]}  # prints a b c

To copy an array, use subscript @, surround it with quotes, and surround that with parentheses:

foo=(a b c)
echo ${bar[1]}    # prints b

Do not try to copy with just the variable:

foo=(a b c)
echo ${bar[1]}    # prints nothing

And, do not forget the quotes, or else arrays with space-containing elements will be screwed up:

foo=("a 1" "b 2" "c 3")
echo ${bar[1]}            # oops, print "1"
echo ${baz[1]}            # prints "b 2"

Special variables

There are special bash variables for grabbing arguments to scripts and functions:

echo $0      # prints the script name
echo $1      # prints the first argument
echo $2      # prints the second argument
echo $9      # prints the ninth argument
echo $10     # prints the first argument, followed by 0 
echo ${10}   # prints the tenth argument
echo $#      # prints the number of arguments

The variable $? holds the "exit status" of the previously executed process.
An exit status of 0 indicates the process "succeeded" without error.
An exit status other than 0 indicates an error.
In shell programming, true is a program that always "succeeds," and false is a program that always "fails":

echo $?   # prints 0
echo $?   # will never print 0; usually prints 1

The process id of the current shell is available as $$
The process id of the most recently backgrounded process is available as $!:

# sort two files in parallel:
sort words > sorted-words &        # launch background process
sort -n numbers > sorted-numbers & # launch background process
wait $p1
wait $p2
echo Both files have been sorted.

Operations on variables

In a feature unique among many languages, bash can operate on the value of a variable while dereferencing that variable.
String replacement
Bash can replace a string with another string:
foo="I'm a cat."
echo ${foo/cat/dog}  # prints "I'm a dog."

To replace all instances of a string, use double slashes:

foo="I'm a cat, and she's cat."
echo ${foo/cat/dog}   # prints "I'm a dog, and she's a cat."
echo ${foo//cat/dog}  # prints "I'm a dog, and she's a dog."

These operations generally do not modify the variable:

echo ${foo/hello/goodbye}  # prints "goodbye"
echo $foo                  # still prints "hello"

Without a replacement, it deletes:

foo="I like meatballs."
echo ${foo/balls}       # prints I like meat.

The ${name#pattern} operation removes the shortest prefix of ${name} matching pattern, while ## removes the longest:

echo ${minipath#/usr}           # prints /bin:/bin:/sbin
echo ${minipath#*/bin}          # prints :/bin:/sbin
echo ${minipath##*/bin}         # prints :/sbin

The operator % is the same, except for suffixes instead of prefixes:

echo ${minipath%/usr*}           # prints nothing
echo ${minipath%/bin*}           # prints /usr/bin:
echo ${minipath%%/bin*}          # prints /usr
String/array manipulation
Bash has operators that operate on both arrays and strings.
For instance, the prefix operator # counts the number of characters in a string or the number of elements in an array.

It is a common mistake to accidentally operate on the first element of an array as a string, when the intent was to operate on the array.

Even the Bash Guide for Beginners contains a misleading example:

ARRAY=(one two three)
echo ${#ARRAY}          # prints 3 -- the length of the array?

However, if we modify the example slightly, it seems to break:

ARRAY=(a b c)
echo ${#ARRAY}          # prints 1

This is because ${#ARRAY} is the same as ${#ARRAY[0]}, which counts the number of characters in the first element, a.
It is possible to count the number of elements in the array, but the array must be specified explicitly with @:

ARRAY=(a b c)
echo ${#ARRAY[@]}      # prints 3

It is also possible to slice strings and arrays:

string="I'm a fan of dogs."
echo ${string:6:3}           # prints fan

array=(a b c d e f g h i j)
echo ${array[@]:3:2}         # prints d e
Existence testing
Some operations test whether the variable is set:

unset username
echo ${username-default}        # prints default

echo ${username-default}        # prints admin

For operations that test whether a variable is set, they can be forced to check whether the variable is set and not empty by adding a colon (":"):

unset foo
unset bar

echo ${foo-abc}   # prints abc
echo ${bar:-xyz}  # prints xyz


echo ${foo-123}   # prints nothing
echo ${bar:-456}  # prints 456

The operator = (or :=) is like the operator -, except that it also sets the variable if it had no value:

unset cache echo ${cache:=1024}   # prints 1024
echo $cache           # prints 1024

echo ${cache:=2048}   # prints 1024
echo $cache           # prints 1024

The + operator yields its value if the variable is set, and nothing otherwise:

unset foo
unset bar
echo ${foo+42}    # prints 42
echo ${bar+1701}  # prints nothing

The operator ? crashes the program with the specified message if the variable is not set:

 : ${1?failure: no arguments} # crashes the program if no first argument

(The : command ignores all of its arguments, and is equivalent to true.)
Indirect look-up
Bash allows indirect variable/array look-up with the ! prefix operator.
That is, ${!expr} behaves like ${${expr}}, if only that worked:

echo ${!foo}  # prints $bar, which is 42
alpha=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
echo ${!char} # prints ${alpha[12]}, which is m

Array quirks: * versus @

There are two additional special variables: $* and $@.
[All of the behaviors described in this section apply to arrays when accessed via ${array[*]} or ${array[@]} as well.]

The both seem to contain the arguments passed to the current script/procedure, but they have subtly different behavior when quoted:
To illustrate the difference, we need to create a couple helper scripts.

First, create print12:

# prints the first parameter, then the second:
echo "first:  $1"
echo "second: $2"
Then, create showargs:
echo $*
echo $@

echo "$*"
echo "$@"

bash print12 "$*"
bash print12 "$@"

Now, run showargs:

$ bash showargs 0  " 1    2  3"

to print:

0 1 2 3
0 1 2 3
0  1    2  3
0  1    2  3
first:  0  1    2  3
first:  0
second:  1    2  3

This happens because "$*" combines all arguments into a single string, while "$@" requotes the individual arguments.
There is another subtle difference between the two: if the variable IFS (internal field separator) is set, then the contents of this variable are spliced between elements in "$*".

Create a script called atvstar:

echo $*
echo $@
echo "$*"
echo "$@"

And run it:

$ bash atvstar 1 2 3 

to print:

1 2 3
1 2 3
1 2 3
IFS must contain a single character.

Again, these same quoting behaviors transfer to arrays when subscripted with * or @:

 arr=("a b"  " c d    e")
 echo ${arr[*]}            # prints a b c d e
 echo ${arr[@]}            # prints a b c d e
 echo "${arr[*]}"          # prints a b  c d    e
 echo "${arr[@]}"          # prints a b  c d    e
 bash print12 "${arr[*]}"  
 # prints:
 # first:  a b  c d    e
 # second:

 bash print12 "${arr[@]}"
 # prints:
 # first:  a b
 # second:  c d    e

Strings and quoting

Strings in bash are sequences of characters.
To create a literal string, use single quotes; to create an interpolated string, use double quotes:

foo='Hello, $world!'
bar="Hello, $world!"
echo $foo            # prints Hello, $world!
echo $bar            # prints Hello, Earth!

In intepolated strings, variables are converted to their values.


In bash, variable scope is at the level of processes: each process has its own copy of all variables.
In addition, variables must be marked for export to child processes:

bash somescript          # somescript cannot see foo

export foo

bash somescript          # somescript can see foo

echo "foo = " $foo       # always prints foo = 42

Let's suppose that this is somescript:

echo "old foo = $foo"
echo "new foo = $foo"
The output from the code would be:
old foo = 
new foo = 300
old foo = 42
new foo = 300
foo = 42

Expressions and arithmetic

It is possible to write arithmetic expressions in bash, but with some caution.
The command expr prints the result of arithmetic expressions, but one must take caution:

expr 3 + 12      # prints 15
expr 3 * 12      # (probably) crashes: * expands to all files 
expr 3 \* 12     # prints 36

The (( assignable = expression )) assignment notation is more forgiving:

(( x = 3 + 12 )); echo $x    # prints 15
(( x = 3 * 12 )); echo $x    # prints 36

If you want the result of an arithmetic expression without assigning it, you can use $((expression)):

echo $(( 3 + 12 ))   # prints 15
echo $(( 3 * 12 ))   # prints 36

While declaring variables implicitly is the norm in bash, it is possible to declare variables explicitly and attach a type to them.

The form declare -i variable creates an explicit integer variable:

declare -i number
echo $number        # prints 42

echo $another       # prints 2+4*10

echo $number        # prints 0

Assignments to integer variables will force evaluation of expressions.

Files and redirection

Every process in Unix has access to three input/output channels by default: STDIN (standard input), STDOUT (standard output) and STDERR (standard error).

When writing to STDOUT, the output appears (by default) at the console.

When reading from STDIN, it reads (by default) directly from what the user types into the console.

When writing to STDERR, the output appears (by default) at the console.
All of these channels can be redirected.

For instance, to dump the contents of a file into STDIN (instead of accepting user input), use the < operator:

# prints out lines in myfile containing the word foo:
grep foo < myfile 

To dump the output of a command into a file, use the > operator:

# concatenates file1 with file2 in new file combined:cat file1 file2 > combined 

To append to the end of a file, use the >> operator:

# writes the current date and time to the end of a file named log:date >> log

To specify the contents of STDIN literally, in a script, use the <<endmarker notation:
All of this will be printed out.
Since all of this is going into cat on STDIN.

Everything until the next instance of endmarker by itself on a line is redirected to STDIN.
To redirect error output (STDERR), use the operator 2>:

# writes errors from web daemon start-up to an error log:httpd 2> error.log

In fact, all I/O channels are numbered, and > is the same as 1>.
STDIN is channel 0, STDOUT is channel 1, while STDERR is channel 2.
The notation M>&N redirects the output of channel M to channel N.

So, it's straightforward to have errors display on STDOUT:

grep foo nofile 2>&1 # errors will appear on STDOUT

Capturing STDOUT with backquotes

There is another quoting form in bash that looks like a string--backtick: ``.
These quotes execute the commands inside of them and drop the output of the process in place:
 # writes the date and the user to the log:
 echo `date` `whoami` >> log  
Given that is sometimes useful to nest these expansions, newer shells have added a nestable notation: $(command):
 # writes the date and the user to the log:
 echo $(date) $(whoami) >> log  
It is tempting to import the contents of a file with `cat path-to-file`, but there is a simpler built-in shorthand: `<path-to-file`:
 echo user: `<config/USER` # prints the contents of config/USER

Redirecting with exec

The special bash command exec can manipulate channels over ranges of commands:
 exec < file # STDIN has become file
 exec > file # STDOUT has become file
You may wish to save STDIN and STDOUT to restore them later:
 exec 7<&0 # saved STDIN as channel 7
 exec 6>&1 # saved STDOUT as channel 6
If you want to log all output from a segment of a script, you can combine these together:
 exec 6>&1       # saved STDOUT as channel 6
 exec > LOGFILE  # all further output goes to LOGFILE

 # put commands here

 exec 1>&6       # restores STDOUT; output to console again


It is also possible to route the STDOUT of one process into the STDIN of another using the | (pipe) operator:
 # prints out root's entry in the user password database:
 cat /etc/passwd | grep root 
The general form of the pipe operator is:
 outputing-command | inputing-command
And, it is possible to chain together commands in "pipelines":
 # A one-liner to find space hogs in the current directory:

 # du -cks *  # prints out the space usage
              # of files in the current directory

 # sort -rn   # sorts STDIN, numerically,
              # by the first column in reverse order

 # head       # prints the first 10 entries from STDIN

 du -cks * | sort -rn | head
Some program accept a filename from which to read instead of reading from STDIN.
For these programs, or programs which accept multiple filenames, there is a way to create a temporary file that contains the output of a command, the <(command) form.
The expression <(command) expands into the name of a temporary file that contains the output of running command.
This is called process substitution.
 # appends uptime, date and last line of event.log onto main.log:
 cat <(uptime) <(date) <(tail -1 event.log) >> main.log


Bash excels at coordinating processes.
Pipelines act to coordinate several processes together.
It is also possible to run processes in parallel.
To execute a command in the background, use the & postfix operator:
 time-consuming-command &
And, to fetch the process id, use the $! special variable directly after spawning the process:
 time-consuming-command &
The wait command waits for a process id's associated process to finish:
 time-consuming-command &
 wait $pid
 echo Process $pid finished.
Without a process id, wait waits for all child processes to finish.
To convert a folder of images from JPG to PNG in parallel:
for f in *.jpg
  convert $f ${f%.jpg}.png &
echo All images have been converted.

Globs and patterns

Bash provides uses the glob notation to match on strings and filenames.
In most contexts in bash, a glob pattern automatically expands to an array of all matching filenames:
 echo *.txt        # prints names of all text files
 echo *.{jpg,jpeg} # prints names of all JPEG files
Glob patterns have several special forms:
  • * matches any string.
  • ? matches a single character.
  • [chars] matches any character in chars.
  • [a-b] matches any character between a and b.
Using these patterns, it's easy to remove all files of the form fileNNN, where NNN is some 3-digit number:
 rm file[0-9][0-9][0-9]
The curly brace "set" form seems to act like a pattern, but it will expand even if the files do not exist: {string1,string2,...,stringN} expands to string1 or string2 or ...
It is possible to create a "bash bomb": a pattern that grows exponentially in size under expansion:
 echo {0,1}              # prints 0 1

 echo {0,1}{0,1}         # prints 00 01 10 11

 echo {0,1}{0,1}{0,1}    # prints 000 001 010 011 100 101 110 111

Control structures

Like most languages, bash supports control structures for conditionals, iteration and subroutines.


If-then-else-style conditionals exist in bash, as in other languages.
However, in bash the condition is a command, and an exit status of success (0) is "true," while an exit status of fail (non-zero) is "false.":
# this will print:
if true
  echo printed

# this will not print:
if false
  echo not printed
Bash can take different actions on whether a program succeeded or failed:
if httpd -k start
  echo "httpd started OK"
  echo "httpd failed to start"
In bash, many conditions are built from the special command test.
The command test takes many flags to perform conditional tests.
Run help test to list them all.
Some popular flags include:
  • -e file is true iff a specific file/directory exists.
  • -z string is true iff the given string is empty.
  • string1 = string2 is true iff the two strings are equal.
There is an alternate notation for test args using square brackets: args ].
Conditionals can check if arguments are meaningful:
 if [ "$1" = "-v" ]
   echo "switching to verbose output"


The while command; do commands; done form executes commands until the test command completes with non-zero exit status:
 # automatically restart the httpd in case it crashes:
 while true
It's possible to iterate over the elements in an array with a for var in array; do commands; done loop:
 # compile all the c files in a directory into binaries:
 for f in *.c
   gcc -o ${f%.c} $f


Bash subroutines are somewhat like separate scripts.
There are two syntaxes for defining a subroutine:
function name {
name () {
Once declared, a function acts almost like a separate script: arguments to the function come as $n for the nth argument.
One major different is that functions can see and modify variables defined in the outer script:

function showcount {
  echo $count

showcount    # prints 20

echo $count  # prints 30


Putting this all together allows us to write programs in bash.
Here is a subroutine for computing factorial:
function fact {
  while [ "$n" -ge 1 ]
    result=$(expr $n \* $result)
    n=$(expr $n - 1)
  echo $result
Or, with the expression notation:
function facter {
  while (( n >= 1 ))
    (( result = n * result ))
    (( n = n - 1 ))
  echo $result
Or, with declared integer variables:
factered () {
  declare -i result
  declare -i n


  while (( n >= 1 ))

  echo $result

Tuesday, April 14, 2020

Bash Grep Multiple Pattern matching

Search Multiple Words / String Pattern Using grep Command on Bash shell

How do I search multiple strings or words using the grep command? For example I’d like to search word1, word2, word3 and so on within /path/to/file. How do I force grep to search multiple words? How can I grep for multiple patterns on Linux, OS X, FreeBSD, or Unix-like system? What is the command to search multiple words in Linux?

The grep command supports regular expression pattern. To search multiple patterns, use the following syntax:
How do I grep for multiple patterns?
The syntax is:
  1. Use single quotes in the pattern: grep 'pattern*' file1 file2
  2. Next use extended regular expressions: egrep 'pattern1|pattern2' *.py
  3. Finally, try on older Unix shells/oses: grep -e pattern1 -e pattern2 *.pl

Grep searching two words in a line

Here are all other possibilities for grep and egrep command:

grep 'word1\|word2\|word3' /path/to/file
### Search all text files ###
grep 'word*' *.txt
### Search all python files for 'wordA' or 'wordB' ###
grep 'wordA*'\''wordB' *.py
grep -E 'word1|word2' *.doc
grep -e string1 -e string2 *.pl
egrep "word1|word2" *.c

In this example, search warning, error, and critical words in a text log file called /var/log/messages, enter:
$ grep 'warning\|error\|critical' /var/log/messages
To just match words, add the -w option:
$ grep -w 'warning\|error\|critical' /var/log/messages
Use the egrep command and you can skip the above syntax to search three words:
$ egrep -w 'warning|error|critical' /var/log/messages

How to find multiple strings in files?

Let us try a few more examples with additional options passed to the grep/egrep:
$ grep -e 'warning\|error\|critical' /var/log/messages
I recommend that you pass the -i (ignore case) and --color option as follows too:
$ egrep -wi --color 'warning\|error\|critical' /var/log/messages

To search all *.conf files under /etc/, enter:
# egrep -wi --color 'foo|bar' /etc/*.conf
To search recursively (including sub-directories) listed, run:
# egrep -Rwi --color 'foo|bar' /etc/
Where options are as follows:
  • -R : Recursive search
  • -w : Match only words
  • -i : Ignore case distinctions. In other words match FOO, foo, Foo and so on.
  • --color : Surround the matched in color on the terminal. For example, display matched strings in colors.

Bash Condition Comparisons

Compare Numbers, Strings and Files in Bash Shell Script

IF / THEN in bash follow the same basic syntax:
if [ conditions/comparisons]
if [2 -gt 3]
     print "2 is greater"
     print "2 is not greater"

Numeric Comparisons

This is one the most common evaluation method i.e. comparing two or more numbers. We will now create a script for doing numeric comparison, but before we do that we need to know the parameters that are used to compare numerical values . Below mentioned is the list of parameters used for numeric comparisons
VAL1 -eq VAL2 is VAL1 is equal to VAL2  
VAL1 -ge VAL2 is 
VAL1 is greater than or equal to VAL2  
VAL1 -gt VAL2 is 
VAL1 is greater than VAL2  
VAL1 -le VAL2 is 
VAL1 is less than or equal to VAL2  
VAL1 -lt VAL2 is 
VAL1 is less than VAL2
VAL1 -ne VAL2 is 
VAL1 is not equal to VAL2  
Now that we know all the parameters that are used for numeric comparisons, let’s use these in a script,
# Script to do numeric comparisons
if [ $var2 -gt $var1 ]
        echo "$var2 is greater than $var1"
# Second comparison
If [ $var1 -gt 30]
        echo "$var is greater than 30"
        echo "$var1 is less than 30"
This is the process to do numeric comparison, now let’s move onto string comparisons.

Strings Comparisons

When creating a bash script, we might also be required to compare two or more strings & comparing strings can be a little tricky. For doing strings comparisons, parameters used are
VAL1 VAL2 checks if VAL1 is the same as string VAL2
VAL1 != VAL2 checks if VAL1 is not the same as VAL2
VAL1 VAL2 checks if VAL1 is less than VAL2
VAL1 VAL2 checks if VAL1 is greater than VAL2
-n VAL1 checks if VAL1 has a length greater than zero
-z VAL1 checks if VAL1 has a length of zero
Note :-  You might have noticed that greater than symbol (>) & less than symbol (<) used here are also used for redirection for stdin or stdout in Linux. This can be a problem when these symbols are used in our scripts, so what can be done to address this issue.
Solution is simple , when using any of these symbols in scripts, they should be used with escape character i.e. use it as “/>” or “/<“.
Now let’s create a script doing the string comparisons.
In the script, we will firstly be checking string equality, this script will check if username & our defined variables are same and will provide an output based on that. Secondly, we will do greater than or less than comparison. In these cases, last alphabet i.e. z will be highest & alphabet a will be lowest when compared. And capital letters will be considered less than a small letter.
# Script to do string equality comparison
if [ $USER = $name ]
                echo "User exists"
                echo "User not found"
# script to check string comparisons
if [ $var1 \> $var2 ]
                echo "$var1 is greater"
                echo "$var2 is greater"
# Lower case  & upper case comparisons
if [ $var3 \> $var1 ]
                echo "$var3 is greater"
                echo "$var1 is greater"
We will now be creating another script that will use “-n” & “-z” with strings to check if they hold any value
# Script to see if the variable holds value or not
var1=" "
if [ -n $var1 ]
                echo "string  is not empty"
                echo "string provided is empty"
Here we only used ‘-n’ parameter but we can also use “-z“. The only difference is that with ‘-z’, it searches for string with zero length while “-n” parameter searches for value that is greater than zero.

File comparison

This might be the most important function of comparison & is probably the most used than any other comparison. The Parameters that are used for file comparison are
-d file                     checks if the file exists and is it’s a directory
-e file                     checks if the file exists on system
-w file                   checks if the file exists on system and if it is writable
-r file                     checks if the file exists on system and it is readable
-s file                     checks if the file exists on system and it is not empty
-f file                     checks if the file exists on system and it is a file
-O file                   checks if the file exists on system and if it’s is owned by the current user
-G file                   checks if the file exists and the default group is the same as the current user
-x file                    checks if the file exists on system and is executable
file A -nt file B     checks if file A is newer than file B
file A -ot file B     checks if file A is older than file B
Here is a script using the file comparison
# Script to check file comparison
if [ -d $dir ]
                echo "$dir is a directory"
                cd $dir
                ls -a
                echo "$dir is not exist"