---
title: "The First Script - Relativity and Variables"
url: "https://courses.osherove.com/courses/automating-all-the-things-with-finalbuilder/the-first-script-relativity-and-variables.md"
canonical: "https://courses.osherove.com/courses/automating-all-the-things-with-finalbuilder/the-first-script-relativity-and-variables/"
tags: []
author: "Roy Osherove"
description: "Lesson 3 of 18 in Automating All the Things with FinalBuilder (Iterations and Variables), 10:50. Free video by Roy Osherove."
usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)."
license: "https://creativecommons.org/licenses/by/4.0/"
---

# The First Script - Relativity and Variables

1. [Courses](https://courses.osherove.com/#courses)
2. [Automating All the Things with FinalBuilder](https://courses.osherove.com/courses/automating-all-the-things-with-finalbuilder/)
3. Iterations and Variables

Lesson 3 of 18

Duration: 10:50 [Watch on YouTube](https://www.youtube.com/watch?v=rr-BIZi0eQw)

## In this lesson

Roy Osherove builds a first [FinalBuilder](https://osherove.com/blog/2005/3/12/cooltool-finalbuilder-30-the-ultimate-build-management-and-a.html "[CoolTool] FinalBuilder 3.0 - the ultimate build management and automation tool (osherove.com)") project that creates a text file and replaces a placeholder in it with the contents of another file, read into a project variable. He uses the built-in FB project directory variable so that the script always runs relative to where the project is, and refactors the repeated folder name into a generation directory variable, whose value can also be changed from the command line.

## Transcript

1,410 words

[\[00:02\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=2s) Okay, so let's start with a very simple project. This is going to be our first project and we want to make sure that our project will always run no matter where we run it from. We run run successfully. So let's say that the first action that is part of our automation project is to create some sort of text file and put some content in it. Right now we're just going to hardcode the content. Then we're going to look for a specific word in the content and replace it with some other word. So the first thing we want to do is we want to create a new project here

[\[00:32\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=32s) And in our new project we can just search for text the word text here and here you can see that we have write to a text file read create text file so let's do that let's create a text file now where should the text file be I could say C slash or sorry let's try that again create a new text file and say it's going to be on C slash

[\[01:02\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=62s) My text file and it would probably work. But what I want is for this to always work regardless of where I am. So, I don't know if I'm going to have a folder C. Yes, I probably would. But I don't know if I should work on C. So I can say let's make sure that this file is always being created relative to where my current project script is. So what if I use a special variable

[\[01:32\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=92s) And that there are certain built-in variables inside FinalBuilder that we get whenever we execute something. Now all variables start with percent sign. So if I say percent sign you can see some variables that I have access to from here. For example I can say FB prod. So if I if I just say FB you can see that I have a bunch of builtin variables and these will give me some of the locations of my current project.

[\[02:02\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=122s) For example FB project is the full path including the file name of the current running project file. But I want my current directory. So maybe I'll use this variable FB project directory slash new file.txt. Now in this case if the file already exists I want to override it. If the directory is needed I'll create that too. So maybe I'll say I know maybe I'll create another directory say

[\[02:36\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=156s) New files slash something where my new file txt exists. I can choose the encoding here for now I'm okay with an but you know maybe it should be UTF8. And here I'll just say this is some custom stuff.

[\[03:08\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=188s) Put stuff here, something that I can maybe later replace. I'll just put it like this. Okay. So, let's save our text file here. Let's save this project and we'll save it to a directory called let's say we're going to create a directory called in under C we're going to create a directory called FB demo and we're going to call our project file demo one. Okay, if I run this now it ran and I can look in my build log to see what happened.

[\[03:42\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=222s) Existing file found and will be overwritten. Okay. What if I wanted to see that file here? So let me open C slash FB demo and I can see this is my project file and all the locations and I have a new folder called new files and here I have my new file and this is the output. Okay, so far so good. This will always run relative to where my project is.

[\[04:16\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=256s) So let's try to to replace some text in the file with the contents of another file. Let's say that in this directory I'm going to have another file called important.txt.

[\[04:47\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=287s) And in the important txt I have this is important Frank. I don't know who Frank is but he knows who Frank is. So let's say I want to read the contents of that and append that or replace that. So let's read a text file again in this case from my location. So FB project directory slash new files

[\[05:18\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=318s) Slashimp important.txt. By the way, if I now just hover my mouse over here, I will see the full extracted location extrapolated location with the placeholder of FB project dire directory and I can say allow reading while it's in use by another process. And I can now do something for example I can put the contents into a variable. Now which variable can I put this in?

[\[05:50\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=350s) Maybe I should create my own variable here. Let's put a variable here. And so if I wanted to control my variables, I can go here and say in the project level, user level, application level or environment level. These are the environment variables. These are the application level variables. This is the user and specific project. So just for this project I'm going to add important content which is

[\[06:21\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=381s) It's going to be a string obviously but I can just keep it a variant for now. I don't want to make it persistent so it's not going to be saved for the future runs of this code. And it's going not going to be a macro so it's not going to contain other values of other variables. So I save that here and let me move that up by just pressing control up or just going up here move it before before creating I want to read it into a variable and now

[\[06:52\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=412s) I'm going to say important contents. So now it's going to read the the contents from here put them in a variable and now I want that variable to be replaced. So, how do I replace? I look for the word replace. And I can see text find and replace. There's a deprecated one. I want to use that. Just text find and replace. So, in what file? Again, FB project directory.

[\[07:23\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=443s) You can see some repetition. I might want to create a variable to hold all of this stuff together, such as new files slash new file.txt. And I want to search for the string. Replace this. I don't remember what the string is. Let's open that for a second. Put stuff here. Let's replace that with

[\[07:57\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=477s) I want to replace everything that's case sensitive. Replace with replace the text and write back to the source file. And I want to replace it with the value of a variable. So I'm just going to say percent important contents. So what we have here, we read the text file important. We create a test text file with some basic hard-coded stuff and replace the some put stuff here with the contents of important.

[\[08:33\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=513s) So let's see if that actually works. Okay, that finished. We can try to see what's in new file now. We can see this is important, Frank. And this is the custom stuff, which is exactly what we wanted. Now, maybe we should make a variable cuz I see that we keep replacing stuff. Here we have the word new files. We might want to change that directory name as well. So maybe we should use

[\[09:04\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=544s) What's called refactoring. I'm going to I'm going to replace this. going to say going to exit com command x or control x to cut it and say generation directory and put another percent sign here. Now it knows that this doesn't exist but I could press F3

[\[09:41\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=581s) And it will create a variable for that and this will include the default value of new files as I want to. So now I have project deer I have generation deer. If tomorrow I want to change generation deer, I want to only replace it in one place. So I want to create the text file also in generation deer

[\[10:23\]](https://www.youtube.com/watch?v=rr-BIZi0eQw&t=623s) Generation directory. So if tomorrow I want to move all the files to a specific place, I have it just I just have to change the variable value. And the nice thing is I can also change the variable value from a command line. So the disc script will always run relative, but I now have control over where it writes to. So that's a simple example of how you can start automating things and also make them more maintainable by default.

## Related

- [Build Pattern: Location Agnostic Script](https://pipelinedriven.org/article/2014/3/2/build-pattern-location-agnostic-script) · pipelinedriven.org

    Roy's build pattern for scripts that use only relative paths so they run on any machine, as this first script does with the project directory variable.

- [Build Pattern: Fill In the Blanks](https://osherove.com/blog/2013/1/19/build-pattern-fill-in-the-blanks.html) · osherove.com

    Roy's build pattern for using variables as the single source of truth instead of repeating a value, like the generation directory variable in this lesson.

### Also linked in this lesson

#### osherove.com

- [\[CoolTool\] FinalBuilder 3.0 - the ultimate build management and automation tool](https://osherove.com/blog/2005/3/12/cooltool-finalbuilder-30-the-ultimate-build-management-and-a.html)

[Previous lesson Getting Around FinalBuilder (Demo)](https://courses.osherove.com/courses/automating-all-the-things-with-finalbuilder/getting-around-finalbuilder-demo/) [Next lesson Variables that Contain Variables](https://courses.osherove.com/courses/automating-all-the-things-with-finalbuilder/variables-that-contain-variables/)


---

## About the author

**Roy Osherove**: Senior Solutions Architect at AWS working on AI for production and AI-driven development; author of The Art of Unit Testing and Elastic Leadership, with about 20 years of consulting and training on unit testing, TDD, team leadership and continuous delivery.

### Sites

- [RobotPaper](https://robotpaper.ai/): This blog: AI patterns and anti-patterns, AI and coding agents, and engineering leadership.
- [osherove.com](https://osherove.com): Roy's personal site. Author of The Art of Unit Testing and Elastic Leadership; consulting and training on unit testing, TDD, team leadership and continuous delivery, plus about 20 years of blog posts.
- [The Art of Unit Testing](https://www.artofunittesting.com): The Art of Unit Testing, 3rd Edition (Manning): readable, maintainable, trustworthy unit tests, plus TDD workshops in C#, JavaScript, Java and Kotlin.
- [5whys.com](https://www.5whys.com): Roy's writing on software team leadership: self-organizing teams, surviving chaos, learning mode and the Elastic Leadership model.
- [Pipeline Driven](https://pipelinedriven.org): Continuous delivery and DevOps practices: build patterns, pipeline-friendly testing, DevOps metrics and enterprise DevOps.
- [Elastic Leadership](https://www.elasticleadership.com): Elastic Leadership, Roy's framework for software team leaders (survival, learning and self-organizing modes).

### Social

- X: https://x.com/royosherove
- LinkedIn: https://www.linkedin.com/in/osherove/

### Contact

- Contact form: https://forms.gle/jQSx5KoXvrVA1JCK7

### License

Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page). License: https://creativecommons.org/licenses/by/4.0/
