PRODUCT






Home









Free Download








Installation Instructions





FAQ





FAQ








Ask A Question





LEARN SCRIPTING





Overview








Lesson 1








2


3


4


5








Exam





SAMPLE SCRIPTS





Computer








Internet








Administrators








Developers








Data








Miscellaneous





HELP / DOCUMENTATION





Commands








Automated Internet








Automated Editors








Sample Scripts








Precompiled Functions








System Features






Learning Scripting - Lesson 5
(system command, sen command, File Search, Script development techniques)

In this lesson, we will learn a couple of new commands - system and sen. We will implement the file search mechanism using the sen command. We will look at some of the script development techniques. As part of the discussion, we will develop a script to search emails on a computer.



PREPARATION
  1. Did you understand the important concepts in the last lesson ? If not, please take a look at that lesson again. Look at the words, phrases and sentences in red color. Make sure you understand them.
  2. Start biterScripting. Enter the following command exactly as you see it below. Then press the ENTER key.

    Command
    script "http://www.biterscripting.com/LearningScripting/Prep5.txt"


    Keep biterScripting open throughout this lesson. Make C:/LearningScripting/Lesson5 the current directory, by entering the following command. (This directory was created by the above script command.)

    Command
    ccd "C:/LearningScripting/Lesson5"




  3. Open the system viewer. Go to directory C:/LearningScripting/Lesson5. We will use this directory throughout this lesson.






5.1. SYSTEM COMMAND

The system command automates mouse clicking and keyboard typing. Some examples of automation:

  • Double clicking on a file to open that file
  • Double clicking on an executable to start a program
  • Moving a file by dragging and dropping it
  • Making a copy of a file using CTRL-C and CTRL-V
  • Renaming a directory by right clicking on it


I will demonstrate. Go to your system viewer. Go to directory C:/LearningScripting/Lesson5. Double click on file Sample5.txt. The file is opened in a text editor. Close the text editor (and the file).

Now, enter the following commands in biterScripting input area.

Commands
ccd "C:/LearningScripting/Lesson5"
system "sample5.txt"


The file sample5.txt was opened in a text editor. The system command simulated the double-click behavior. Go ahead and close the text editor (and the file). Now, let's try something else. In the system viewer, go to directory C:/LearningScripting/Lesson5. Drag and drop file Sample5.txt from directory C:/LearningScripting/Lesson5 to directory C:/LearningScripting/Lesson4. This moves the file from one directory to another. Now, we will move this file back using the system command. Enter the following command.

Commands
ccd "C:/LearningScripting/Lesson5"
system move "C:/LearningScripting/Lesson4/sample5.txt" "C:/LearningScripting/Lesson5"


Check in the system viewer. You will see that file sample5.txt is back in directory C:/LearningScripting/Lesson5. I will now list some of the common usages of the system command.

The system commands for files
CommandType of behaviorDescription of the behavior
system file_name_with_extension_.exeDouble clicking on an executable or a program.That executable or the program is started.
system file_name_with_extension_other_than_.exeDouble clicking on a file that is not an executable.That file is opened with the default program associated with that extension. For example, a .txt file will be opened in a text editor.
system copy file1 file2Copying and pasting a file.file1 will be copied as file2.
system copy file1 directory2Copying a file, then pasting it into a directory.file1 will be copied to directory2. It will have the same file name.
system rename file1 file2Right clicking a file, then renaming it.file1 will be renamed file2.
system move file1 directory2Dragging and dropping a file from one directory to another.file1 will be moved to directory2. It will have the same name.
system delete file1Clicking on a file, then pressing the delete key.file1 will be deleted.


The system commands for directories
system mkdir directory1Right clicking within a directory, then selecting new.A new directory will be created. Its name will be directory1.
system rmdir directory1Selecting a directory, then pressing the delete key.The directory1 will be deleted if it is empty. (Yes, there is a command to delete a directory even if it is not empty. But, that activity is best done manually and not automated in a script.)


There are commands that do other things with directories - rename, copy, move, etc. But I recommend that you do those things manually upon some reflection. So, I would rather not tell you about those commands.

The system command waits until the operating system completes the tasks it was assigned by the system command.

QUESTION 5.1 Write commands that will make a new directory C:/LearningScripting/Lesson5/test, then copy file C:/LearningScripting/Lesson5/Sample5.txt to that newly created directory. Answer



QUESTION 5.2 Create a script file copyall.txt in directory C:/LearningScripting/Lesson5 that will create a new directory C:/LearningScripting/Lesson5/test2, the copy all .txt files in directory C:/LearningScripting (and its subdirectories) to that directory. Answer





5.2. SEN COMMAND

We looked at the lex (line extractor) command earlier, which was part of a class of commands known as Automated Editors. Another useful command in this class is the sen command.

The sen command (string enumerator or counter) counts instances of a string in an input string. In other words, it counts how many times a specified string appears inside an input string. The string whose instances are being counted is called the search string . The syntax of this command includes the sen command followed by a string followed by the input string. Enter the following command.

Command
sen "^bcd^" "abcdefghijklmnopqrstuvwxyz"


The above command counts how many times the string "bcd" appears inside of the input string. The input string is "abcdefghijklmnopqrstuvwxyz". The search string is "bcd". The command's output is 1. That means there is 1 instance of string "bcd" inside the input string. In other words, the search string "bcd" appears one time inside the input string.

It is important to note that the search string is enclosed within symbols ^ . This symbol is called a caret.

QUESTION 5.3 How many times does the search string "bcd" appear inside the input string "b cd bcd bbcd bd bc" ? Answer

The search string and the input string can both be passed using string variables. That's where the power of sen (and other automated editor commands) comes in. Enter the following commands.

Commands
var string content
cat "C:/LearningScripting/Lesson5/Sample5.txt" > $content
sen "^Rome^" $content


The output is 1, since the search string "Rome" appears once inside the content of file Sample5.txt. Verify this by viewing the file Sample5.txt from system viewer, by double clicking on it. Also, check in that file, that there is a word "dallas" - it is all in lower case lettters. How can we search for a string inside the contents of a file irrespective of the case ? This is accomplished using the -c option of the sen command. The -c option directs the sen command to do a case-independent or case-insensitive search. Enter the following commands.

Commands
cat "C:/LearningScripting/Lesson5/Sample5.txt" > $content
sen "^Dallas^" $content
sen -c "^Dallas^" $content


The first sen command will return 0, since it does not have the -c option, and without the -c option, "dallas" does not match "Dallas". The second sen command returns 1, since it has the -c option. With the -c option, "dallas", "Dallas", "DALLAS", "daLAas" will all match the search string "Dallas".

We can redirect the stream output from the sen command to a string variable. We can then check the value of that string variable. If it is "0", our search string is not present in the file. If it is anything else, the search string is present in the file.

We have just discovered a trick to check if a search string appears inside a file using the sen command. It is called the File Search mechanism. We will elaboreate on it in the next section.

QUESTION 5.4 Read the help page for the sen command. What do you need to do if the search string itself contains a caret (^), such as, if "a^b" is the search string ? Answer





5.3. FILE SEARCH

File Search is a mechanism to check if a string is present inside a file. It is implemented by reading a file into a string variable, then using the sen command on that variable. The string to search for, is called, again, the search string. Let's create a script for the file search mechanism. Create the following script filesearch.txt in directory C:/LearningScripting/Lesson5.

Script filesearch.txt
##################################################################
# SCRIPT filesearch.txt
##################################################################
# This script checks if a particular search string is present inside a file.
##################################################################

# We will read the contents of the file into the following string variable.
var string content

# Read the contents of the file into $content.
repro "C:/LearningScripting/Lesson5/Sample5.txt" > $content

# We will use the sen command to check if the search string is present
# in $content. We will use the -c option to do a case-independent search.
# We will redirect the output of the sen command to the following string variable.
var string output
sen -c "^Dallas^" $content > $output

# If $output is "0", the search string is not present. If $output is
# anything else, the search string is present.
if ($output <> "0")
do
    # Search string is present.
    echo "Search string is present."
done
endif


We will build this script together step-by-step. I will list the script after each step. I will show the newly added commands (and comments) in the blue color. Please edit the script step-by-step as we go along. Save the script file after each step, but keep the file open.

Let's make this filesearch.txt script more general. Currently, the file to search is hard-coded as "C:/LearningScripting/Lesson5/Sample5.txt". Let's pass the file as an argument to this script.

Script filesearch.txt
##################################################################
# SCRIPT filesearch.txt
##################################################################
# This script checks if a particular search string is present inside a file.
#
# The input argument file is the file to search in.
#
# The caller should call this script as following.
#
# script filesearch.txt file("C:/LearningScripting/Lesson5/Sample5.txt")
##################################################################
# Input argument file - the file to search in.
var string file


# We will read the contents of the file into the following string variable.
var string content

# Read the contents of the file into $content.
repro $file > $content

# We will use the sen command to check if the search string is present
# in $content. We will use the -c option to do a case-independent search.
# We will redirect the output of the sen command to the following string variable.
var string output
sen -c "^Dallas^" $content > $output

# If $output is "0", the search string is not present. If $output is
# anything else, the search string is present.
if ($output <> "0")
do
    # Search string is present.
    echo "Search string is present."
done
endif


Next thing, instead of searching for a fixed (hard-coded) string "Dallas", we will pass the search string also as an input argument. We will declare a string variable called search_string, and pass its value using FVA - Forward Variable Assignment.

There is a bit of a problem here. The caller to our script will pass us the search_string as "Dallas". We need to enclose it in carets (^) before using it in the sen command. To do that, we will declare a string variable called sen_argument, assign its value as a caret, followed by $search string, followed by another caret. We will then use the variable $sen_argument in the sen command. (This is a rather useful trick - so make sure you understand the code that does this trick.)

Script filesearch.txt
##################################################################
# SCRIPT filesearch.txt
##################################################################
# This script checks if a particular search string is present inside a file.
#
# The input argument file is the file to search in.
#
# The input argument search_string is the string to search for.
#
# The caller should call this script as following.
#
# script filesearch.txt file("C:/LearningScripting/Lesson5/Sample5.txt") search_string("Dallas")
##################################################################
# Input argument file - the file to search in.
var string file

# Input argument search_string - the string to search for.
var string search_string

# We will read the contents of the file into the following string variable.
var string content

# Read the contents of the file into $content.
repro $file > $content

# We will create the argument for the sen command in a separate string variable.
# It will have the value of caret (^), followed by the value of $search_string,
# followed by the closing caret.
var string sen_argument
set $sen_argument = "^" + $search_string + "^"

# We will use the sen command to check if the search string is present
# in $content. We will use the -c option to do a case-independent search.
# We will redirect the output of the sen command to the following string variable.
var string output
sen -c $sen_argument $content > $output

# If $output is "0", the search string is not present. If $output is
# anything else, the search string is present.
if ($output <> "0")
do
    # Search string is present.
    echo "Search string is present."
done
endif


That's it. Execute the script with the following command.

Command
script "C:/LearningScripting/Lesson5/filesearch.txt" file("C:/LearningScripting/Lesson5/Sample5.txt") search_string("Dallas")


You can now use this script to search any file on your computer for any search string. You may not have yet realized the power of this script. We saw earlier that biterScripting does NOT make a distinction between local files and web pages. That means we can use our filesearch.txt script to search not only the local files, but also web pages on any web site. I will demonstrate with the next question.

QUESTION 5.5 Does the web page at http://www.biterscripting.com contain the word "now" ? Does it contain the word "later" ? Answer



We will use the power of the script filesearch.txt in the next section, where we will build a script to perform searches on emails on a computer. (Have you evern lost email addresses of old friends ? This script may be for you.)



5.4. SCRIPT DEVELOPMENT TECHNIQUES

In this section, we will see learn some of the commonly used script development techniques. As part of the discussion, we will develop a new script emailsearch.txt that will search emails on your computer for a specific search string.

Take a look at your email program. Find out in which directory it stores emails on your computer. This is called the email storage directory. (Many operating systems use the term 'folder' instead of directory. Similarly, some email programs use the term 'storage folder' for the directory where they store emails.) Emails are stored in files in that directory and its subdirectories. Each file contains one email. These files are called email files. Find out what extension your email program uses for email files.

For example, if you use Outlook Express (Outlook Express is a trademark, service mark, or other forms of intellectual property of its respective owner.), you can go in Tools->Options->Advanced->Maintenance->Store Folder to find out the email storage directory. Also, the extension for email files is .eml.

Since I don't know your specific email storage directory and the extension of email files, I will use an example for each of them.

  • Email storage directory - we will use C:/LearningScripting/Lesson5 .
  • Extension for email files - we will use .eml .
We will now begin to develop the script. I will write each script development technique in red color, then explain it, then follow it up with our example script - emailsearch.txt.



  1. Don't just write a script, tell a story !

    Use comments generously throughout a script. Tell the readers what the script does, how it does it, what each variable does. Tell the readers what command options you are using to make a command behave a certain way. Tell them about any special tricks you are using. Show them examples of how the script is to be invoked. Write comments that cover all of these. There are several benefits of having generous comments within a script.

    • If you don't use a script for a while, then need to start using it again, you will quickly understand what the script is doing and how.
    • If you need to change a script based on changed requirements, you will quickly know what changes are needed and where to put them in.
    • When you need to write a brand-new script, you can look at other scripts you have developed, and quickly figure out which ones you can reuse for your brand-new requirements.
    • If you share scripts that you have developed with others, other users of your scripts can quickly understand what the script does and how it is doing it.


  2. Document requirements well.

    Script requirements are documented using description of what the script does. Using comments at the top of the script, tell the reader what the script does. Make these documented requirements as descriptive and as explicit as possible. Mention any gotchas and exceptions that the script does not handle.

    We will start developing our emailsearch.txt script by first documenting requirements. Create a new script file emailsearch.txt in directory C:/LearningScripting/Lesson5 with the following code.

    Script emailsearch.txt
    ##################################################################
    # SCRIPT emailsearech.txt
    ##################################################################
    # This script searches email files on a local computer based on
    # a search string. The script lists the email file name and the
    # contents of the email file, for each email file that contains
    # the search string.
    ##################################################################


    As before, we will develop this script in steps. I will show the new code and comments added or changed within each step in blue color. Save the script file after each step, but keep the file open for for further editing.


  3. Define input arguments.

    Input arguments to a script are passed using FVA - Forward Variable Assignment. Define input arguments before you begin to write a script. Document them with comments at the top of the script. Tell the reader how these input arguments are to be assigned with examples. Tell the reader what default values will be used if these input arguments are not assigned.

    The first part of the script code should include declarations of the input arguments using the var command. This part of the code should also include checking if input arguments are assigned, and if not, assigning them default values.

    Script emailsearch.txt
    ##################################################################
    # SCRIPT emailsearech.txt
    ##################################################################
    # This script searches email files on a local computer based on
    # a search string. The script lists the email file name and the
    # contents of the email file, for each email file that contains
    # the search string.
    #
    # The script accepts following input arguments.
    #
    # storagedir - directory where email files are stored. If not assigned,
    # current directory will be used.
    #
    # files - a file pattern for email files. If not assigned,
    # "*" will be used, which means all files will
    # be treated as email files.
    #
    # search_string - the search string. Email files will be searched for
    # this string. If not assigned, an empty search string will be
    # used, which will return errors.
    #
    # Call this script as following.
    #
    # script "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")
    #
    ##################################################################

    # Declare input arguments.
    var string storagedir, files, search_string

    # Is $storagedir assigned ? If not, assign current directory.
    if ($storagedir == "")
        scd > $storagedir
    endif

    # Is $files assigned ? If not, assign "*".
    if ($files == "")
        set $files = "*"
    endif

    # We don't need to check if $search_string is assigned. If not assigned, the script will return
    # errors.





  4. Use descriptive variable names.

    Descriptive variable names instantly convey to the reader what those variables are for. In our example script - emailsearch.txt, we could have called the input arguments x, y and z, instead of, storagedir, files and search_string. But, x, y and z, don't really convey to the reader what these variables are for. Variable names sd (for storagedir), f (for files) and ss (search_string) could also have been used. They are a little better than x, y and z. But, still the reader would have to scratch his/her head a bit to figure out what these variables are for. We chose the variable names storagedir, files and search_string because they are fully descriptive.



  5. Break up the functionality into small tasks.

    Breaking up functionality of a script into small tasks, makes a complex problem simpler. In our example script emailsearch.txt, we know that we need to do the following tasks.

    • Task 1 - Collect a list of email files that match the file pattern $files in directory $storagedir. Loop thru these files one by one.
    • Task 2 - Check if the search string $search_string is present in an email file.
    • Task 3 - If the search string is present in an email file, print the file name, followed by the contents of the file.


    Having broken up our script into smaller tasks does make our script development much easier. (Some students find it easier to do this task breakup in writing - that clarifies the tasks much better for them. The writing can be done on a piece of paper or the write-up can just be included in the script itself as comments. Other students prefer to do this task breakup in their head. I will leave it up to you to do the task breakup using a method that you are most comfortable with.)



  6. Reuse. Reuse. Reuse.

    For each task within a script, think of a script or code that you have already developed. Then reuse that code using copy-paste-edit approach as follows.

    • Copy relevant part of the script or code you have already developed.
    • Paste that part into the current script you are developing.
    • Edit that part to meet the requirements of the current script you are developing.


    We identified three tasks above. We have already developed several scripts through these lessons. Let's identify which ones we can reuse for each of our tasks identified above.

    • Task 1 - To collect a list of email files, then loop thru these files one by one we can reuse the script filedirloop.txt. We created that script in Lesson 4, and stored it in directory C:/LearningScripting/Lesson4. It is based on the technique called the File Directory Loop.
    • Task 2 - To check if a search string is present in a file, we can reuse the script filesearch.txt. We developed it in this lesson and stored it in directory C:/LearningScripting/Lesson5. It is based on the File Search mechanism.
    • Task 3 - To print the file name, followed by the contents of the file, we can reuse the script reprofiles2.txt. It is also based on the File Directory Loop technique. We created that script in Lesson4 (in response to Question 4.4) and stored in directory C:/LearningScripting/Lesson4.


    There are several advantages to reusing. I will list a few.

    • Confidence - You know that you are reusing scripts and code that have already been tested and are working correctly.
    • Speed - You can increase the speed of your script development. In a shorter time, you can create a rich collection of scripts that automate a lot of things for you.
    • Modularity - Often times, instead of copy-paste-edit'ing a previous script into the script you are currently developing, you can simply call that script from your current script with the script command. This helps compartmentalize the script's functionality, as well as shorten the sizes of your various scripts. A shorter script is more manageable.


    You can consider reusing scripts from any of the following sources.

    • Scripts you have written.
    • Sample scripts provided as part of biterScripting and on biterscripting.com web site.
    • Scripts written by other people whom you know.
    • Several scripts are posted on various web sites. These scripts are written by various people. They developed these scripts for their own requirements, then posted them for others who may have similar requirements. (When reusing scripts from people you personally don't know - be careful. Make sure you completely understand the script before you use it.)




  7. Develop the script in steps.

    Add the code for one task at a time. Test the script after each step. This allows you to gradually debug and fix your script - one task in each step.

    We will now go ahead, and add code for Task 1 in our script. We will reuse the code from script filedirloop.txt in directory C:/LearningScripting/Lesson4. In our newly learnt style of commenting generously, we will add comments to the reused code.

    Script emailsearch.txt
    ##################################################################
    # SCRIPT emailsearech.txt
    ##################################################################
    # This script searches email files on a local computer based on
    # a search string. The script lists the email file name and the
    # contents of the email file, for each email file that contains
    # the search string.
    #
    # The script accepts following input arguments.
    #
    # storagedir - directory where email files are stored. If not assigned,
    # current directory will be used.
    #
    # files - a file pattern for email files. If not assigned,
    # "*" will be used, which means all files will
    # be treated as email files.
    #
    # search_string - the search string. Email files will be searched for
    # this string. If not assigned, an empty search string will be
    # used, which will return errors.
    #
    # Call this script as following.
    #
    # script "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")
    #
    ##################################################################

    # Declare input arguments.
    var string storagedir, files, search_string

    # Is $storagedir assigned ? If not, assign current directory.
    if ($storagedir == "")
        scd > $storagedir
    endif

    # Is $files assigned ? If not, assign "*".
    if ($files == "")
        set $files = "*"
    endif

    # We don't need to check if $search_string is assigned. If not assigned, the script will return
    # errors.

    # Use the lf command to collect a list of email files. The first argument to the
    # lf command is file pattern, we have that in $files. The second argument is
    # the directory, we have that in $storagedir.
    var string list
    lf -rn $files $storagedir > $list
    while ($list <> "")
    do
        # Get the next file into a string variable.
        var string filedir
        lex "1" $list > $filedir
        # The next file is now in $filedir.
    done






  8. Use test data.

    Until the script is completely developed, tested and debugged, and until you are satisfied that it is working correctly, use small test data, instead of real data. In our case, we are developing a script that searches emails. So, instead of trying the script out with your real emails at this stage, it is best to copy a few of your email files into a test directory.

    A few test email files are already downloaded into directory C:/LearningScripting/Lesson5. This was done as part of the preparation for this lesson, when you executed the Prep5.txt script. Type the following command to see the contents of these email files.

    Command
    repro "*.eml"




  9. Use -p, -l options of the script command.

    We are developing our emailsearch.txt script in steps. In each step, it is a recommended practice to test the script with the -p and -l options of the script command. The -p option tells biterScripting to only parse the script and not to execute it. If there are any syntax errors, they will be checked with the -p option. The -l option tells biterScripting to list command and comment lines in the script. (Without the -l option, the script command does not list command and comment lines.) If an error is present, it will be listed immediately below the command line that is causing that error. The -p and -l options can be combined as -pl.

    Go ahead and test our script so far with the following command.

    Command
    script -pl "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")


    If the word 'Ready' appears in the status area, there are no syntax errors.


  10. Use debug statements.

    We talked, in an earlier lesson, about inserting debug statements in a script, with the -e option of the echo command. Let's put it to practice. Insert the debug statements in the emailsearch.txt script as below.

    Script emailsearch.txt
    ##################################################################
    # SCRIPT emailsearech.txt
    ##################################################################
    # This script searches email files on a local computer based on
    # a search string. The script lists the email file name and the
    # contents of the email file, for each email file that contains
    # the search string.
    #
    # The script accepts following input arguments.
    #
    # storagedir - directory where email files are stored. If not assigned,
    # current directory will be used.
    #
    # files - a file pattern for email files. If not assigned,
    # "*" will be used, which means all files will
    # be treated as email files.
    #
    # search_string - the search string. Email files will be searched for
    # this string. If not assigned, an empty search string will be
    # used, which will return errors.
    #
    # Call this script as following.
    #
    # script "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")
    #
    ##################################################################

    # Declare input arguments.
    var string storagedir, files, search_string

    # Is $storagedir assigned ? If not, assign current directory.
    if ($storagedir == "")
        scd > $storagedir
    endif

    # Is $files assigned ? If not, assign "*".
    if ($files == "")
        set $files = "*"
    endif

    # We don't need to check if $search_string is assigned. If not assigned, the script will return
    # errors.

    echo -e "DEBUG: Looking for search_string " $search_string " in files " $files " in directory " $storagedir

    # Use the lf command to collect a list of email files. The first argument to the
    # lf command is file pattern, we have that in $files. The second argument is
    # the directory, we have that in $storagedir.
    var string list
    lf -rn $files $storagedir > $list
    while ($list <> "")
    do
        # Get the next file into a string variable.
        var string filedir
        lex "1" $list > $filedir
        # The next file is now in $filedir.
        echo -e "DEBUG: Processing file " $filedir
    done


    Let's execute our script, first with the -pl options, then without the -pl options.

    Commands
    script -pl "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")
    script "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")






  11. Keep the number of command lines in any one script small.

    It makes a script more manageable if the number of command lines (not counting comment lines and blank lines) within the script is small. Up to 50 command lines is very good. Up to 100 command lines is ok. Anything more than 100 command lines indicates some restructuring may be required - you may want to consider breaking that script up into two or more scripts.

    For example, we now need to add the code for Task 2 to our emailsearch script - code that will check if the search string $search_string is present in an email file. We have already developed a separate script for that - filesearch.txt. So, instead of copying the code for that script into this script, why don't we simply call that script from this script, as follows ?

    Script emailsearch.txt
    ##################################################################
    # SCRIPT emailsearech.txt
    ##################################################################
    # This script searches email files on a local computer based on
    # a search string. The script lists the email file name and the
    # contents of the email file, for each email file that contains
    # the search string.
    #
    # The script accepts following input arguments.
    #
    # storagedir - directory where email files are stored. If not assigned,
    # current directory will be used.
    #
    # files - a file pattern for email files. If not assigned,
    # "*" will be used, which means all files will
    # be treated as email files.
    #
    # search_string - the search string. Email files will be searched for
    # this string. If not assigned, an empty search string will be
    # used, which will return errors.
    #
    # Call this script as following.
    #
    # script "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")
    #
    ##################################################################

    # Declare input arguments.
    var string storagedir, files, search_string

    # Is $storagedir assigned ? If not, assign current directory.
    if ($storagedir == "")
        scd > $storagedir
    endif

    # Is $files assigned ? If not, assign "*".
    if ($files == "")
        set $files = "*"
    endif

    # We don't need to check if $search_string is assigned. If not assigned, the script will return
    # errors.

    echo -e "DEBUG: Looking for search_string " $search_string " in files " $files " in directory " $storagedir

    # Use the lf command to collect a list of email files. The first argument to the
    # lf command is file pattern, we have that in $files. The second argument is
    # the directory, we have that in $storagedir.
    var string list
    lf -rn $files $storagedir > $list
    while ($list <> "")
    do
        # Get the next file into a string variable.
        var string filedir
        lex "1" $list > $filedir
        # The next file is now in $filedir.
        echo -e "DEBUG: Processing file " $filedir

        # Is the $search_string present in file $filedir ?
        var string output
        script "filesearch.txt" file($filedir) search_string($search_string) > $output
        if ($output == "Search string is present.")
        do
            # Search string is present. List file name and file contents.
        done
        endif
    done


    Let's take a look at the call to script filesearch.txt. One of its arguments is passed using the syntax
    search_string($search_string). The search_string outside the parentheses is the input argument - it is a variable declared inside the script being called - filesearch.txt. This is the variable whose value is being assigned.

    The $search_string inside the parentheses is the value that is being assigned. $search_string is a variable declared inside this script - emailsearch.txt. They both happen to have the same name, and that's quite acceptable.

    We will execute our script again, first with the -pl options, then without the -pl options.

    Commands
    script -pl "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")
    script "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")




The last thing we want to do is to add the code for Task 3 - print the file name, followed by the contents of the file. For that, we are going to reuse the script reprofiles2.txt in directory C:/LearningScripting/Lesson4. Let's copy-paste-edit that code in as follows.

Script emailsearch.txt
##################################################################
# SCRIPT emailsearech.txt
##################################################################
# This script searches email files on a local computer based on
# a search string. The script lists the email file name and the
# contents of the email file, for each email file that contains
# the search string.
#
# The script accepts following input arguments.
#
# storagedir - directory where email files are stored. If not assigned,
# current directory will be used.
#
# files - a file pattern for email files. If not assigned,
# "*" will be used, which means all files will
# be treated as email files.
#
# search_string - the search string. Email files will be searched for
# this string. If not assigned, an empty search string will be
# used, which will return errors.
#
# Call this script as following.
#
# script "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")
#
##################################################################

# Declare input arguments.
var string storagedir, files, search_string

# Is $storagedir assigned ? If not, assign current directory.
if ($storagedir == "")
    scd > $storagedir
endif

# Is $files assigned ? If not, assign "*".
if ($files == "")
    set $files = "*"
endif

# We don't need to check if $search_string is assigned. If not assigned, the script will return
# errors.

echo -e "DEBUG: Looking for search_string " $search_string " in files " $files " in directory " $storagedir

# Use the lf command to collect a list of email files. The first argument to the
# lf command is file pattern, we have that in $files. The second argument is
# the directory, we have that in $storagedir.
var string list
lf -rn $files $storagedir > $list
while ($list <> "")
do
    # Get the next file into a string variable.
    var string filedir
    lex "1" $list > $filedir
    # The next file is now in $filedir.
    echo -e "DEBUG: Processing file " $filedir

    # Is the $search_string present in file $filedir ?
    var string output
    script "filesearch.txt" file($filedir) search_string($search_string) > $output
    if ($output == "Search string is present.")
    do
        # Search string is present. List file name and file contents.
        echo "\n\n =========== EMAIL FILE " $filedir " =========== "
        repro $filedir
    done
endif
done


We will execute our script again, first with the -pl options, then without the -pl options.

Commands
script -pl "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")
script "emailsearch.txt" storagedir("C:/LearningScripting/Lesson5") files("*.eml") search_string("joe")


Test the script in various ways with our test emails. Once you think it is working correctly, you can do two things.

  • Remove all debug statements.
  • Move both scripts emailsearch.txt and filesearch.txt to directory C:/Scripts where they will be available to everyone using your computer.
If you noticed, our emailserach.txt is actually rather small - without the comments and blank lines. It has about 21 lines, which fits our recommendation of keeping the number of command lines in a script small. I will list the script below without comments and blank lines.

Script emailsearch.txt - without comments and blank lines
var string storagedir, files, search_string
if ($storagedir == "")
    scd > $storagedir
endif
if ($files == "")
    set $files = "*"
endif var string list
lf -rn $files $storagedir > $list
while ($list <> "")
do
    var string filedir
    lex "1" $list > $filedir
    var string output
    script "filesearch.txt" file($filedir) search_string($search_string) > $output
    if ($output == "Search string is present.")
    do
        echo "\n\n =========== EMAIL FILE " $filedir " =========== "
        repro $filedir
    done
endif
done




QUESTION 5.6 What search string can we use to find emails from email address <joe@8m906dh7.com> ? Answer

A more general email search script is provided on the biterScripting web site as a sample script called SS_FindEmailStrs .



DID YOU KNOW ?
  1. When you enter a script command, and specify the script file using either the full path or the relative path, how does biterScripting know where to find the script file ? If there are two script files by the same name in two separate directories, how does biterScripting know which one to use ? biterScripting finds (and uses) the script file in the following sequence.
    1. If you specify the script file using full path, there is only one script file at that full path. biterScripting will use that file.
    2. If you specify the script file using relative path, biterScripting first checks if a file by that name exists at that relative path, relative to the current directory. If the file exists, it will be used. If not, biterScripting will continue its search as below.
    3. biterScripting will look at the value of the system variable $path. It contains a list of directories separated by the verticle bar (|) (also known as a pipe). biterScripting will check if the script file exists at the relative path you specified, relative to each directory in this list. As soon as a file is found, it will use that file.
    4. If after doing all of the above, still a file is not found, an error will be produced indicating that the script file could not be found.


    The value of $path is set by default to "C:/Scripts". (You can change this value.) It is thus best to store all your 'proven' scripts in the directory C:/Scripts.

  2. You can execute scripts directly from a web site. This is done by specifying the script file with a web path. For example, the following command will execute script Prep5.txt at the web address http://www.biterscripting.com/LearningScripting/.

    Command
    script "http://www.biterscripting.com/LearningScripting/Prep5.txt"


    In fact, that's what we have been doing when we used the script command in preparation for each of the lessons. (These preparation scripts were creating directories, downloading sample files, etc. all needed for the lessons.) Note that you can execute scripts from any web site, not only biterscripting.com. This means, once you have written scripts that are working well, and you believe that your scripts will be useful to others, you can publish your scripts on a web site. You can also post them at various forums. (As a reverse consideration, as always, make sure you understand well the scripts written by other people, before you use them.)





SUMMARY
In this lesson, we learned
  1. The system command.
  2. The sen command.
  3. The file search mechanism.
  4. Several script development techniques.
  5. We developed an email search script.




HOMEWORK 5
  1. Revisit the important concepts we learned in this lesson. (Look at this page from top to bottom. The important concepts are the words, phrases or sentences in red color.) Did you understand them ? Answer
  2. Our script emailsearch.txt searches email files for one search string. Create a script called emailsearch2.txt in directory C:/LearningScripting/Lesson5 that searches email files based on two search strings. Instead of one input argument search_string, this script will take two input arguments - search_string1 and search_string2. It will list email files and their contents for files that contain both search strings . Answer




Well, that's it for the lessons. The next is exam.

Hopefully, you gained enough knowledge in these lessons to go on your own. We could not cover many topics - other data types, expressions and conversion rules, variable overloading, global variables, system functions, writing your own functions, inline commands, automated editors, regular expressions, use of biterScripting in batch mode, scheduling scripts to run periodically using a scheduler, running scripts as part of a web server - to name a few. You will come across these topics as you develop more advanced scripts. When more knowledge is needed, always use the help pages, look at sample scripts, ask people who are experts in biterScripting for help.

We enjoyed working with you through these lessons. We wish you many productive, rewarding and money-making scripting engagements.

Please don't forget to take the exam and submit your answers.




2008-2014, biterScripting.com. All rights reserved.
biterScripting, biterScript, biterBrowser, biterMobile, biterScripting.com, FVA (Forward Variable Assignment) are trademarks of biterScripting.com. Is it biterScripting-compatible ? is a service mark of biterScripting.com. Explorer, Unix, Windows are trademarks, service marks or other forms of intellectual property of their respective owners.