## FreeBASIC File/Folder Management:

### by Stephane Richard (MystikShadows)

### INTRODUCTION:

Many times when programming an application (or even games) you find yourself coming across the subject of creating files folders (or deleting them) for more than one reason. Luckily FreeBASIC has everything we need to help us with all of these functionalities.

In this tutorial I'll cover all of the file/folder oriented statements and functions that exist in FreeBASIC and well see how and when they can be used in order to bring some good standard file and folder management functionality to your programming projects. So let's start off with a little reference of the commands we'll be using and take it from there.

### FREEBASIC FILE AND FOLDER COMMANDS AND FUNCTIONS:

There are several commands and functions available to create, delete, manage files and folders.

- NAME: CHDIR
  SYNTAX: CHDIR "Drive:\Path"
  Result = CHDIR("Drive:\Path")
  This function simply goes to the folder specified as a parameter. This path can include drive name and path.
- NAME: CURDIR | CURDIR$
  SYNTAX: CURDIR$
  CurrentPath = CURDIR$
  This function returns the current path that the system is currently in. If you change folder with the CHDIR command above and display CURDIR$ again you'll see that it changed to reflect the new folder location.
- NAME: DIR | DIR$
  SYNTAX: DIR FileSpec, AttribMask, OutAttrib
  CurrentFile = DIR("*.*", fbDirectory)
  This function looks in the current path (or in the specified folder) for the occurrence of the file specification passed in the first parameter. If it finds it, it will return the name of the first occurrence. If it does not find it, it will return an empty string (""). Once a first file is found you can use the DIR() function without parameters in a loop to get the following occurrences of the file specification you are looking for (more on this later. fbDirectory and other constants are defined in "dir.bi" include file.
- NAME: KILL
  SYNTAX: KILL "FileSpecification"
  Result = KILL("*.TMP")
  This function deletes the file specification from either the current folder or the folder specified in the parameter. If the deletion went well, a 0 will be returned. If an error occurred, that error number will be returned by the KILL function.
- NAME: MKDIR
  SYNTAX: MKDIR "FolderName"
  Result = MKDIR("MyNewFolder\MyNewSubFolder")
  This function creates a folder in the local file system. It will return zero (0) if it worked, or minus one (-1) if an error occurred.
- NAME: NAME
  SYNTAX: NAME "OldName", "NewName"
  Result = NAME("OldName.Ext", "NewName.Ext")
  This function renames a file to a new given name. It can also rename a group of files using file masks. IF it works it will return zero (0). If some error occurred and the file could not be renamed, an error number will be returned by the function.
- NAME: RMDIR
  SYNTAX: RMDIR "FolderName"
  Result = RMDIR("C:\TEMP\")
  This function will attempt to remove a directory from the specified path or current folder (if just a folder name is specified as a parameter). It will return zero (0) if everything worked or minus one (-1) if an error occurred. RMDIR will not remove a folder in which a file exists.

And now that we have the reference material we need let's see what we can do with them. We will take each one and see how to use them in given situations and perhaps implement some safeguards in code to help minimize errors that could occur. For this we will create our own little COMMAND.COM so to speak. A little program that will accept input from the user and perform the current actions required by the commands we'll enter in the system.

### BUILDING OUR OWN COMMAND PROCESSOR:

As a first note, I'd like to point out that this will be a very simplistic command processor. it's purpose is to highlight the FreeBASIC commands and functions for file/folder manipulation, so it will essentially be a simple loop with string manipulation to decipher the commands entered. But it will be something functional that can later be altered to perform as expected. It will not allow to execute other files for examples, just internal commands for the purpose of this tutorial. The sample program created here can be acquired from this link so you don't have to type or edit anything.

First off we'll create the core processor/command acquisition system and we'll add commands to it as we progress in this tutorial. The framework itself shown here has functions to get parts of the entered command, this is how we'll know which command has been entered and what to do with them.

>     ' -------------------------------------
>     '  BASIC command processor application
>     '          by MystikShadows
>     ' -------------------------------------

>     #INCLUDE "dir.bi"

>     ' -------------------------------
>     '  Sub and Function Declarations
>     ' -------------------------------
>     DECLARE SUB PrintApplicationInformation()
>     DECLARE SUB DisplayHelpScreen()
>     DECLARE SUB ProcessCommand(ToBeProcessed AS STRING)
>     DECLARE FUNCTION GetWordCount(WorkString AS STRING) AS INTEGER
>     DECLARE FUNCTION GetWordNumber(WorkString AS STRING, WordNumber AS LONG) AS STRING

>     ' -----------------------------
>     '  Needed Constant Definitions
>     ' -----------------------------
>     CONST False = 0
>     CONST True  = NOT False

>     CONST HeaderColor  = 15 ' White
>     CONST InfoColor    = 11 ' Light Cyan
>     CONST CommandColor = 14 ' Yellow
>     CONST ErrorColor   = 12 ' Light Red
>     CONST ResultColor  = 10 ' Light Green

>     ' -------------------------
>     '  Needed Global Variables
>     ' -------------------------
>     DIM SHARED CurrentCommand AS STRING
>     DIM SHARED CanExit        AS INTEGER

>     ' ------------------------------------------------------
>     '  Start by displaying the title and general information
>     ' ------------------------------------------------------
>     WIDTH 80, 50
>     COLOR 7, 1
>     CLS
>     CALL PrintApplicationInformation()

>     ' -----------------------------------------------------
>     '  Main loop where commands are acquired and processed
>     ' -----------------------------------------------------
>     DO WHILE CanExit = False
>        ' ---------------------------
>        '  Get command from the user
>        ' ---------------------------
>        COLOR CommandColor, 1
>        PRINT "->";
>        INPUT CurrentCommand
>        CALL ProcessCommand(CurrentCommand)
>        ' -------------------------------------------
>        '  We Clear the command, ready for a new one
>        ' -------------------------------------------
>        CurrentCommand = ""

>     LOOP

>     ' ========================================================
>     '  NAME........: PrintApplicationInformation()
>     '  PARAMETERS..: None
>     '  RETURN......: No value
>     '  ASSUMES.....: Nothing
>     '  CALLED FROM.: Main Program Loop
>     ' --------------------------------------------------------
>     '  DESCRIPTION.: This Sub simply displays some regular
>     '                information to the user about this
>     '                current program
>     ' ========================================================
>     SUB PrintApplicationInformation()

>         COLOR HeaderColor, 1
>         PRINT "MystikShadow's Command Processor Application"
>         PRINT "Version 1.00a"
>         PRINT
>         COLOR InfoColor, 1
>         PRINT "Type 'HELP' for a list of commands"
>         PRINT "Type 'EXIT' to end the program"
>         PRINT

>     END SUB

>     ' ========================================================
>     '  NAME........: DisplayHelpScreen()
>     '  PARAMETERS..: None
>     '  RETURN......: No Value
>     '  ASSUMES.....: Nothing
>     '  CALLED FROM.: The Main Program Loop
>     ' --------------------------------------------------------
>     '  DESCRIPTION.: This Sub displays a list of valid
>     '                commands available to the user. So that
>     '                he/she can learn the allowed commands.
>     ' ========================================================
>     SUB DisplayHelpScreen()

>         COLOR ResultColor, 1
>         PRINT "Valid Commands Are:"
>         PRINT
>         PRINT "TIME                       Returns The Current Time"
>         PRINT "DATE                       Returns The Current Date"
>         PRINT "CD []            Returns Current Path or Changes to PathName"
>         PRINT "DIR     Lists files that match FileSpecification
>         PRINT "REN      Renames an existing file to a new name"
>         PRINT "RENAME   Renames an existing file to a new name"
>         PRINT "MD             Creates a Directory on the Disk"
>         PRINT "RD             Removes a Directory from the disk"
>         PRINT "DEL     Removes a Directory from the disk"
>         PRINT "DELETE  Removes a Directory from the disk"
>         PRINT
>     END SUB

>     ' ========================================================
>     '  NAME........: ProcessCommand()
>     '  PARAMETERS..: ToBeProcessed AS STRING
>     '  RETURN......: No Value
>     '  ASSUMES.....: ToBeProcessed Is Not Empty
>     '  CALLED FROM.: Main Program Loop
>     ' --------------------------------------------------------
>     '  DESCRIPTION.: This Sub is the main core of the program
>     '                it will take the passed command in it's
>     '                parameter, parse it and perform the
>     '                corresponding action.
>     ' ========================================================
>     SUB ProcessCommand(ToBeProcessed AS STRING)

>         ' -------------------------------------
>         '  First we take care of easy commands
>         ' -------------------------------------
>         COLOR ResultColor, 1
>         SELECT CASE TRIM$(UCASE$(ToBeProcessed))
>                CASE "HELP"
>                     CALL DisplayHelpScreen()
>                     EXIT SUB
>                CASE "QUIT"
>                     CLS
>                     END
>         END SELECT

>     END SUB

>     ' ========================================================
>     '  NAME........: GetWordCount()
>     '  PARAMETERS..: WorkString AS STRING
>     '  RETURN......: 0 Or the number of words
>     '  ASSUMES.....: WorkString is valid string with contents
>     '  CALLED FROM.: ProcessCommand()
>     ' --------------------------------------------------------
>     '  DESCRIPTION.: This function accepts a string as a
>     '                parameter, peruses it and accumulates
>     '                the number of words it finds in the
>     '                string.
>     ' ========================================================
>     FUNCTION GetWordCount(WorkString AS STRING) AS INTEGER

>         ' ----------------
>         '  Work Variables
>         ' ----------------
>         DIM  Counter      AS LONG
>         DIM  WordCounter  AS LONG
>         DIM  Position     AS LONG
>         DIM  Skipper      AS LONG

>         ' ----------------------
>         '  Initialize Variables
>         ' ----------------------
>         WordCounter  = 1
>         Position     = 1
>         ' ---------------------------------------------------------
>         '  First we put ourselves at the beginning of the 1st word
>         ' ---------------------------------------------------------
>         IF MID$(WorkString, Position, 1) = " " THEN
>            DO WHILE MID$(WorkString, Position, 1) = " "
>               Position = Position + 1
>            LOOP
>         END IF
>         ' --------------------------------------
>         '  Then we start the Word Count Process
>         ' --------------------------------------
>         FOR Counter = Position TO LEN(WorkString)
>             IF MID$(WorkString, Counter, 1) = " " THEN
>                WordCounter = WordCounter + 1
>                DO WHILE MID$(WorkString, Counter, 1) = " "
>                   Counter = Counter + 1
>                LOOP
>             END IF
>         NEXT Counter
>         ' ----------------------------------------
>         '  Return the number of words accumulated
>         ' ----------------------------------------
>         GetWordCount = WordCounter

>     END FUNCTION

>     ' ========================================================
>     '  NAME........: GetWordNumber()
>     '  PARAMETERS..: WorkString AS STRING
>     '                WordNumber AS LONG
>     '  RETURN......: "" Or the desired word Number
>     '  ASSUMES.....: WorkString has contents, WordNumber > 0
>     '  CALLED FROM.: ProcessCommand()
>     ' --------------------------------------------------------
>     '  DESCRIPTION.: This function accepts a string and a
>     '                Word Number as parameters, it then finds
>     '                the given word number and returns it to
>     '                the calling function.
>     ' ========================================================
>     FUNCTION GetWordNumber(WorkString AS STRING, WordNumber AS LONG) AS STRING

>         ' ----------------
>         '  Work Variables
>         ' ----------------
>         DIM  Counter      AS LONG
>         DIM  WordCounter  AS LONG
>         DIM  Position     AS LONG
>         DIM  Skipper      AS LONG
>         DIM  ReturnString AS STRING

>         ' ----------------------
>         '  Initialize Variables
>         ' ----------------------
>         WordCounter  = 1
>         Position     = 1
>         ReturnString = ""
>         ' ---------------------------------------------------------
>         '  First we put ourselves at the beginning of the 1st word
>         ' ---------------------------------------------------------
>         IF MID$(WorkString, Position, 1) = " " THEN
>            DO WHILE MID$(WorkString, Position, 1) = " "
>               Position = Position + 1
>            LOOP
>         END IF
>         ' --------------------------------------
>         '  Then we start the Word Count Process
>         ' --------------------------------------
>         FOR Counter = Position TO LEN(WorkString)
>             IF MID$(WorkString, Counter, 1) = " " THEN
>                WordCounter = WordCounter + 1
>                DO WHILE MID$(WorkString, Counter, 1) = " "
>                   Counter = Counter + 1
>                LOOP
>             END IF
>             ' ----------------------------------------------------------
>             '  If it's the wanted word number we put it in ReturnString
>             ' ----------------------------------------------------------
>             IF WordCounter = WordNumber THEN
>                IF MID$(WorkString, Counter, 1) <> " " THEN
>                   ReturnString = ReturnString + MID$(WorkString, Counter, 1)
>                END IF
>             END IF
>         NEXT Counter
>         ' ---------------------------------
>         '  Return the word in ReturnString
>         ' ---------------------------------
>         GetWordNumber = ReturnString

>     END FUNCTION

What this does code so far is wait for the user to enter a command in the system. Once entered, the ProcessCommand() subroutine is called. As you can see from the code to ProcessCommand() subroutine so far we manage two commands HELP and QUIT. The last two functions you see in the code are the string manipulation function we'll need to get the different parts of the command entered by the user. If you compile the program like it is now, run it and enter the help command. Here's what you will see on the screen:

After that, just enter EXIT to leave the program. The command list you see on the screenshot are the commands we will be implementing in this tutorial. Four of the commands (CLS, TIME, DATE and CD without parameters are very easy to code for so in the ProcessCommand we'll just add CASE statements for each of them. Here's what the ProcessCommand() subroutine should look like:

>     	SUB ProcessCommand(ToBeProcessed AS STRING)

>         ' -------------------------------
>         '  We take care of easy commands
>         ' -------------------------------
>         COLOR ResultColor, 1
>         SELECT CASE TRIM$(UCASE$(ToBeProcessed))
>                CASE "TIME"
>                     PRINT TIME$
>                     PRINT
>                     EXIT SUB
>                CASE "DATE"
>                     PRINT DATE$
>                     PRINT
>                     EXIT SUB
>                CASE "CLS"
>                     COLOR 7, 1
>                     CLS
>                     EXIT SUB
>                CASE "CD"
>                     PRINT CURDIR$
>                     PRINT
>                     EXIT SUB
>                CASE "HELP"
>                     CALL DisplayHelpScreen()
>                     EXIT SUB
>                CASE "EXIT"
>                     CLS
>                     END
>         END SELECT

In the case of these commands, as you can see, what goes on is very straightforward. Simple code is executed in each of these cases. now we need to add validation and tell the user if they entered a command that isn't recognized. Since we already have the list of valid command it will be rather easy to know if the command entered is valid or not. So We'll add, at the beginning of the subroutine, a condition to ProcessCommand() to validate the command like so:

>     	SUB ProcessCommand(ToBeProcessed AS STRING)

>         DIM FirstWord AS STRING

>         ' -------------------------------------------------
>         '  First we test of the command is a valid command
>         ' -------------------------------------------------
>         FirstWord = TRIM$(UCASE$(GetWordNumber(ToBeProcessed, 1)))
>         IF FirstWord <> "TIME"   AND FirstWord <> "DATE" AND _
>            FirstWord <> "CLS"    AND FirstWord <> "CD"   AND _
>            FirstWord <> "CD.."   AND FirstWord <> "CD\"  AND _
>            FirstWord <> "DIR"    AND FirstWord <> "REN"  AND _
>            FirstWord <> "RENAME" AND FirstWord <> "DEL"  AND _
>            FirstWord <> "DELETE" AND FirstWord <> "MD"   AND _
>            FirstWord <> "RD"     AND FirstWord <> "HELP" AND _
>            FirstWord <> "EXIT"   THEN
>            COLOR ErrorColor, 1
>            PRINT "An Invalid Command Was Entered"
>            PRINT
>            EXIT SUB
>         END IF

>         ' ------------------------------------
>         '  Next we take care of easy commands
>         ' ------------------------------------
>         COLOR ResultColor, 1
>         SELECT CASE TRIM$(UCASE$(ToBeProcessed))
>                CASE "TIME"
>                     PRINT TIME$
>                     PRINT
>                     EXIT SUB
>                CASE "DATE"
>                     PRINT DATE$
>                     PRINT
>                     EXIT SUB
>                CASE "CLS"
>                     COLOR 7, 1
>                     CLS
>                     EXIT SUB
>                CASE "CD"
>                     PRINT CURDIR$
>                     PRINT
>                     EXIT SUB
>                CASE "HELP"
>                     CALL DisplayHelpScreen()
>                     EXIT SUB
>                CASE "EXIT"
>                     CLS
>                     END
>         END SELECT

>     END FUNCTION

Note that I added "CD.." and "CD\" as valid commands because typical DOS users didn't put spaces for these two commands (just a hint of user consideration). Basically, if the command entered isn't one that appears in the if statement we will warn the user that an invalid command has been entered.

### ADDING COMMANDS TO THE COMMAND PROCESSOR:

Now that we validate our commands it's time to get to the real part of the tutorial. This is were we start to really look at what the user wants to do. To do so, we'll need a few other variables in our ProcessCommand() subroutine. We will put them at the beginning of the subroutine after the first DIM statement already there.

>     	DIM SecondWord    AS STRING
>         DIM ThirdWord     AS STRING
>         DIM WorkFile      AS STRING
>         DIM WordCounter   AS INTEGER
>         DIM FolderCounter AS INTEGER
>         DIM FileCounter   AS INTEGER

These variables will come in handy to implement the rest of the supported commands. As you can see from the screenshot SecondWord and ThirdWord are there get the 2nd and 3rd part of the statement (since 2 parameters will be the most we need to deal with we only need SecondWord and ThirdWord). First we'll Implement the CD family of commands. After the SELECT CASE that's already there, we will first add statements to get the second and third word if we need to in order to complete the statements entered by the user. Here is the code to add at the end of the ProcessCommand() subroutine:

>     	' ---------------------------------------------
>         '  We get the rest of the words in the command
>         ' ---------------------------------------------
>         WordConter = GetWordCount(ToBeProcessed)
>         IF WordCounter = 2 THEN
>            SecondWord = GetWordNumber(ToBeProcessed, 2)
>         ELSEIF WordCounter = 3 THEN
>            SecondWord = GetWordNumber(ToBeProcessed, 2)
>            ThirdWord  = GetWordNumber(ToBeProcessed, 3)
>         END IF

Now the first command we will implement is the CD command. Remember that CD by itself simply displays the current directory to the user and is already coded for. This part will take care of the other forms of CD commands. Typically the user will enter CD followed by a folder name, a .. or a \. Like I mentioned earlier DOS users don't usually enter spaces for .. and \ so we will add direct support for CD.. and CD\ without spaces. Here's the code to the CD command:

>     	' -------------------------------------------------------------------------
>         '  This SELECT CASE decides which code to executed for the command entered
>         ' -------------------------------------------------------------------------
>         SELECT CASE FirstWord
>                ' -------------------------------
>                '  THE CD command implementation
>                ' -------------------------------
>                CASE "CD", "CD..", "CD\"
>                     ' -----------------------------------------
>                     '  Test for the existence of the directory
>                     ' -----------------------------------------
>                     IF DIR$(SecondWord, fbDirectory) = "" AND SecondWord <> "\" THEN
>                        ' -------------------------------------------------------
>                        '  If the directory does not exist, we display a message
>                        ' -------------------------------------------------------
>                        COLOR ErrorColor, 1
>                        PRINT "This Directory does not exist. Path remains unchanged."
>                        PRINT CURDIR$
>                        PRINT
>                        COLOR ResultColor
>                     ELSE
>                        ' ------------------------------------------------
>                        '  Test to see if none spaced .. and \ were used
>                        '  Execute appropriate command in these cases.
>                        ' ------------------------------------------------
>                        IF FirstWord = "CD.." THEN
>                           CHDIR ".."
>                        ELSEIF FirstWord = "CD\" THEN
>                           CHDIR "\"
>                        ' ---------------------------------------------------
>                        '  In all other cases we just CHDIR to the directory
>                        ' ---------------------------------------------------
>                        ELSE
>                           ' -----------------------------------------------
>                           '  If it does exist we CHDIR right to the folder
>                           ' -----------------------------------------------
>                           CHDIR SecondWord
>                        END IF
>                        PRINT CURDIR$
>                     END IF
>                     PRINT
>                     EXIT SUB
>         END SELECT

You can note that we also added a test to see if the folder the user wants to change to actually exists. We warn them if it doesn't exist and nothing else happens. If the directory does exist, We use CHDIR to change to the specified directory. Using this code the user can enter any valid CHDIR statements after the CD command and it will perform as expected.

The next command on our list is the MD command. This command is a bit simpler to code for than the CD command because it doesn't have any variants to it. The user would simply type MD FolderName to create the desired folder. We will simply test to see if the folder they are trying to create already exists and warn them if it does. Here's the code for the MD command. It is added to the SELECT CASE statement we just created previously.

>     	  	   ' -------------------------------
>                '  The MD Command Implementation
>                ' -------------------------------
>                CASE "MD"
>                     ' -------------------------------------
>                     '  We test to see if the folder exists
>                     ' -------------------------------------
>                     IF DIR$(SecondWord, fbDirectory) <> "" THEN
>                        ' ------------------------------------
>                        '  If it does exist, we warn the user
>                        ' ------------------------------------
>                        COLOR ErrorColor, 1
>                        PRINT "This Directory already exists, unable to create it."
>                        PRINT
>                        COLOR ResultColor, 1
>                     ELSE
>                        ' -------------------------------------------------------
>                        '  If it doesn't exist, we simply go ahead and create it
>                        ' -------------------------------------------------------
>                        MKDIR SecondWord
>                     END IF
>                     EXIT SUB

As you can see, the code is straight forward and rather clear we either create the folder or we don't (if the folder already exist). This is the only test we really need to do.

Up next on our list is the RD command which removes a directory from the disk. Remember that RD will not work if the directory to be removed already has files in it. Coding for the RD command should be quite similar to the MD command with the added test to see if there are files in the folder we want to remove. If there are, we'll warn the user that they are files. If no files exist in the directory we'll go ahead and use RMDIR to remove the folder.

>     	       ' -------------------------------
>                '  The RD Command Implementation
>                ' -------------------------------
>                CASE "RD"
>                     ' ------------------------------------
>                     '  First we test if the folder exists
>                     ' ------------------------------------
>                     IF DIR$(SecondWord, fbDirectory) = "" THEN
>                        COLOR ErrorColor, 1
>                        PRINT "This Directory does not exist hence cannot be removed."
>                        PRINT
>                        COLOR ResultColor, 1
>                     ' --------------------------------------------------
>                     '  Next we test if there are files in the directory
>                     ' --------------------------------------------------
>                     ELSEIF DIR$(CURDIR$ + "\" + SecondWord + "\*.*") <> "" THEN
>                        COLOR ErrorColor, 1
>                        PRINT "The Directory has files in it and cannot be removed."
>                        PRINT
>                        COLOR ResultColor, 1
>                     ' -----------------------------------------------------
>                     '  If all is good we go ahead and remove the directory
>                     ' -----------------------------------------------------
>                     ELSE
>                        RMDIR SecondWord
>                     END IF
>                     EXIT SUB

Simply put we do two consecutive tests, the first to see if the folder exists in the first place, if it does, we're good we can go to the second test which is to test if the directory has any files in it. If there are files we warn the user since the directory won't be removed. if there are no files we go ahead and remove the directory.

The next command on the list is the DIR command. The DIR command lists files that match the specified File masks. Shortcuts can be used here such as the standard "*.*" and the "?" to filter out unwanted files. In this version I am doing two things when a DIR command is issued. I first list the folders (if any) that match the file mask and then I list the files that match the file mask. I will also accumulate the results to tell the user how many folders and files were found for the DIR command they issued. I added a little feature which if DIR is called without a file mask I default it to *.* instead of warning them of an invalid command. here's the code to the DIR command CASE STATEMENT (again to be added at the end of the SELECT CASE STATEMENT):

>     	       ' --------------------------------
>                '  The DIR Command Implementation
>                ' --------------------------------
>                CASE "DIR"
>                     FolderCounter = 0
>                     FileCounter   = 0
>                     ' ----------------------------------------------------
>                     '  We first list the folders in the current directory
>                     ' ----------------------------------------------------
>                     IF SecondWord = "" THEN
>                        WorkFile = DIR$("*", fbDirectory)
>                     ELSE
>                        WorkFile = DIR$(SecondWord, fbDirectory)
>                     END IF
>                     DO WHILE TRIM$(WorkFile) <> ""
>                        IF LEFT$(WorkFile, 1) <> "." THEN
>                           FolderCounter = FolderCounter + 1
>                           PRINT WorkFile & "\"
>                        END IF
>                        WorkFile = DIR$()
>                     LOOP
>                     ' -------------------------------------------------
>                     '  We then list the files in the current directory
>                     ' -------------------------------------------------
>                     IF SecondWord = "" THEN
>                        WorkFile = DIR$("*")
>                     ELSE
>                        WorkFile = DIR$(SecondWord)
>                     END IF
>                     DO WHILE TRIM$(WorkFile) <> ""
>                        FileCounter = FileCounter + 1
>                        PRINT WorkFile
>                        WorkFile = DIR$()
>                     LOOP
>                     ' --------------------------------------------------------------
>                     '  We finally display the folder and file counts we accumulated
>                     ' --------------------------------------------------------------
>                     PRINT
>                     PRINT "There were " + STR$(FolderCounter) + _
>                           " directories and " + STR$(FileCounter) + _
>                           " files listed."
>                     PRINT
>                     EXIT SUB

Basically, this code is created to show you examples (hopefully real word examples) on how to use these commands, the things to watch out for when using them and the likes. This is why I do things like check for the existence of a folder before I try to CHDIR to it or something. Nothing happens if there's no files to list. If there are files then they will be listed one after the other as long as the search yields a file. Quite straight forward.

And now we have the DEL and DELETE commands. Like DOS you can used both DEL or DELETE (whatever you are used to) to delete files on your disk. The only test we need to do here is to see if the file they want to delete actually exists, if so, then we use the KILL statement to delete the file. If it does not exist we'll simply warn the user about it and do nothing else. here's the CASE statement for the DEL, DELETE command (you guessed it, at the end of the SELECT CASE statement is where it goes):

>     	       ' -------------------------------------------
>                '  The DEL and DELETE Command Implementation
>                ' -------------------------------------------
>                CASE "DEL", "DELETE"
>                     ' ---------------------------------
>                     '  First we see if the file exists
>                     ' ---------------------------------
>                     IF DIR$(SecondWord) = "" THEN
>                        COLOR ErrorColor, 1
>                        PRINT "This file does not exist, unable to delete it."
>                        PRINT
>                        COLOR ResultColor, 1
>                     ' ----------------------------------------------------------
>                     '  If the file exists we go ahead and use KILL to delete it
>                     ' ----------------------------------------------------------
>                     ELSE
>                        KILL SecondWord
>                     END IF
>                     EXIT SUB

Very simple test that basically says that if the file exists we can delete it, if it does not exist we just let the user know (in which case he will just repeat the command with the right file name the next time around, hopefully). Pretty simple isn't it? I thought so.

And we are at the final command to be implemented, the REN and RENAME commands. This is the only command that needs all three parameters, hence we'll have to do some validation on them to make sure everything is good to perform the renaming of the file in question. First test will be the old file name is not empty. If it is empty we let the user know and we do nothing else (EXIT SUB). The next test is to see that the new file name is not empty. if it is empty, once again, we warn the user and exit the subroutine. If it is not empty we go to the third test which is to see that the old file name actually exists on the current or specified folder. If we're still good after these 3 tests we go ahead and use the NAME statement to rename the old file name (SecondWord) to the new file name (ThirdWord). Here is the last CASE STATEMENT to be added to our codebase:

>     		   ' -------------------------------------------
>                '  The REN and RENAME Command Implementation
>                ' -------------------------------------------
>                CASE "REN", "RENAME"
>                     ' ----------------------------------------------
>                     '  First we test that Old Filename Is not empty
>                     ' ----------------------------------------------
>                     IF SecondWord = "" THEN
>                        COLOR ErrorColor, 1
>                        PRINT "The name of an existing file is needed to rename the file."
>                        PRINT
>                        COLOR ResultColor, 1
>                        EXIT SUB
>                     ' ---------------------------------------------
>                     '  Next we test that New Filename Is not empty
>                     ' ---------------------------------------------
>                     ELSEIF ThirdWord = "" THEN
>                        COLOR ErrorColor, 1
>                        PRINT "A new name is needed to rename the file."
>                        PRINT
>                        COLOR ResultColor, 1
>                        EXIT SUB
>                     ' ----------------------------------------------
>                     '  Finally we test that the old filename exists
>                     ' ----------------------------------------------
>                     ELSEIF DIR$(SecondWord) = "" THEN
>                        COLOR ErrorColor, 1
>                        PRINT "The file you are trying to rename does not exist."
>                        PRINT
>                        COLOR ResultColor, 1
>                        EXIT SUB
>                     ' --------------------------------------------------------------
>                     '  If all went well we go ahead and use NAME to rename the file
>                     ' --------------------------------------------------------------
>                     ELSE
>                        NAME SecondWord, ThirdWord
>                        EXIT SUB
>                     END IF

As you can see, it's really all about implementing some basic tests before performing the actual command just to be sure everything is good, ready and safe to perform the actual command. With these in place the command processor becomes a bit more stable a tool to use for the user and for the user's files and folders of course.

A FEW NOTES:

Now remember this sample program is mean to illustrate the use of the file and folder commands provided by FreeBASIC. Hence the emphasis is on those commands. Of course I could have used another method than input to get the user's commands. I could have done things a bit different (like perhaps add some good Drive, Path and file name validation for example) but the important part is what I do with the file and folder commands themselves.

### IN CONCLUSION

And there you have it, I believe we've covered all of the commands offered by FreeBASIC as far as files and folder management goes. Of course FreeBASIC has more commands (like CHAIN, EXEC, RUN and SHELL) that have the potential to add more functionality to a program such as this command processor sample. This sample is designed to respond to user commands but any of these commands could be coded in a subroutine and called for any purpose from any type of program really. The choice is yours.

As always, I hope this tutorial helped you in some way or another. I hope it was clear but readers tend to read things differently. So, if any of this isn't clear in your head, be sure to email me to let me know what parts is not clear or whatever other comments or questions you may have about this tutorial. Until next, happy coding (and command processing).