diff --git a/.gitignore b/.gitignore
index 1cb0671..ead4b2f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,5 +16,6 @@
 # vendor/
 
 /tags
-/testdata/sunny1/
 /.idea/
+/testdata/sunny1/
+/testdata/sunny2/
diff --git a/go.mod b/go.mod
index ec8b3ad..c3318f4 100644
--- a/go.mod
+++ b/go.mod
@@ -2,4 +2,7 @@ module g.arns.lt/zordsdavini/zord-tree
 
 go 1.16
 
-require github.com/otiai10/copy v1.5.1
+require (
+	g.arns.lt/zordsdavini/abcex v1.0.0
+	github.com/otiai10/copy v1.5.1
+)
diff --git a/go.sum b/go.sum
index 651daea..efe5525 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,5 @@
+g.arns.lt/zordsdavini/abcex v1.0.0 h1:qQqlZ4DMfethCGK4I6yGaLqMrTzKNIshqpINd1l3t0E=
+g.arns.lt/zordsdavini/abcex v1.0.0/go.mod h1:YRcJgts3XZwI+LEkngpfUab3DkUAW387Irpr43hIym8=
 github.com/otiai10/copy v1.5.1 h1:a/cs2E1/1V0az8K5nblbl+ymEa4E11AfaOLMar8V34w=
 github.com/otiai10/copy v1.5.1/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
 github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
diff --git a/testdata/sunny/subcategory/file3.md b/testdata/sunny/subcategory/file3.md
index d7253ff..046b813 100644
--- a/testdata/sunny/subcategory/file3.md
+++ b/testdata/sunny/subcategory/file3.md
@@ -1,5 +1,6 @@
 tags: t1
 description: Če test 3
+option2: it exists
 
 ---
 
diff --git a/tree.go b/tree.go
index 7f1b9cc..539ad07 100644
--- a/tree.go
+++ b/tree.go
@@ -2,10 +2,14 @@ package zord_tree
 
 import (
 	"bufio"
+	"fmt"
+	"g.arns.lt/zordsdavini/abcex"
+	cp "github.com/otiai10/copy"
 	"io/fs"
 	"io/ioutil"
 	"os"
 	"path"
+	"path/filepath"
 	"strings"
 )
 
@@ -28,7 +32,166 @@ func BuildTree(dirPath string, meta []string) (Tree, error) {
 	return readPath(dirPath, []string{}, meta)
 }
 
-func readPath( dirPath string, category []string, meta []string) (Tree, error) {
+func PopulateTree(sourcePath string, destPath string, meta []string) error {
+	id, err := getMaxId(sourcePath)
+	if err != nil {
+		return err
+	}
+
+	id++
+	err = addMissingId(sourcePath, id)
+	if err != nil {
+		return err
+	}
+
+	err = addMissingMeta(sourcePath, meta)
+	if err != nil {
+		return err
+	}
+
+	err = cp.Copy(sourcePath, destPath)
+
+	return err
+}
+
+func addMissingMeta(dir string, meta []string) error {
+	err := filepath.Walk(dir, func(path string, info os.FileInfo, e error) error {
+		if e != nil {
+			return e
+		}
+
+		if info.Mode().IsRegular() {
+			check := map[string]bool{}
+			for _, option := range meta {
+				check[option] = false
+			}
+
+			osf, err := os.Open(path)
+			if err != nil {
+				return err
+			}
+			scanner := bufio.NewScanner(osf)
+			scanner.Split(bufio.ScanLines)
+			for scanner.Scan() {
+				line := scanner.Text()
+				for _, option := range meta {
+					if strings.HasPrefix(line, option+":") {
+						check[option] = true
+					}
+				}
+				if line == "---" {
+					for option, process := range check {
+						if !process {
+							err = addMeta(path, option, "")
+							if err != nil {
+								return err
+							}
+						}
+					}
+
+					break
+				}
+			}
+		}
+		return nil
+	})
+	if err != nil {
+		return err
+	}
+
+	return  nil
+}
+
+func addMissingId(dir string, id int64) error {
+	err := filepath.Walk(dir, func(path string, info os.FileInfo, e error) error {
+		if e != nil {
+			return e
+		}
+
+		if info.Mode().IsRegular() {
+			osf, err := os.Open(path)
+			if err != nil {
+				return err
+			}
+			scanner := bufio.NewScanner(osf)
+			scanner.Split(bufio.ScanLines)
+			for scanner.Scan() {
+				line := scanner.Text()
+				if strings.HasPrefix(line, "id:") {
+					break
+				}
+				if line == "---" {
+					err = addMeta(path, "id", abcex.Encode(id))
+					if err != nil {
+						return err
+					}
+
+					id++
+					break
+				}
+			}
+		}
+		return nil
+	})
+	if err != nil {
+		return err
+	}
+
+	return  nil
+}
+
+func addMeta(path string, option string, value string) error {
+	b, err := ioutil.ReadFile(path) // just pass the file name
+	if err != nil {
+		return  err
+	}
+
+	str := string(b)
+	str = strings.Replace(str, "\n\n---\n", fmt.Sprintf("\n%s: %s\n\n---\n", option, value), 1)
+	err = ioutil.WriteFile(path, []byte(str), 0644)
+
+	return  err
+}
+
+func getMaxId(dir string) (int64, error) {
+	var max int64 = 0
+	err := filepath.Walk(dir, func(path string, info os.FileInfo, e error) error {
+		if e != nil {
+			return e
+		}
+
+		if info.Mode().IsRegular() {
+			osf, err := os.Open(path)
+			if err != nil {
+				return err
+			}
+			scanner := bufio.NewScanner(osf)
+			scanner.Split(bufio.ScanLines)
+			for scanner.Scan() {
+				line := scanner.Text()
+				if line == "---" {
+					break
+				}
+
+				if strings.HasPrefix(line, "id:") {
+					line = strings.TrimPrefix(line, "id:")
+					i := abcex.Decode(strings.Trim(line, " "))
+					if i > max {
+						max = i
+					}
+				}
+			}
+		}
+		return nil
+	})
+	if err != nil {
+		return max, err
+	}
+
+	return max, nil
+}
+
+func readPath(dirPath string, category []string, meta []string) (Tree, error) {
 	tree := Tree{}
 
 	tree.path = dirPath
diff --git a/tree_test.go b/tree_test.go
index c650a42..b3e7c83 100644
--- a/tree_test.go
+++ b/tree_test.go
@@ -67,4 +67,34 @@ func TestMeta(t *testing.T) {
 	if tree.files[0].meta["option1"] != "test option" {
 		t.Error("File 'file1.md' should have 'option1' with value 'test option'")
 	}
-}
\ No newline at end of file
+}
+
+func TestId(t *testing.T) {
+	err := os.Remove("./testdata/sunny1")
+	if err != nil {
+	}
+	err = os.Remove("./testdata/sunny2")
+	if err != nil {
+	}
+	err = cp.Copy("./testdata/sunny", "./testdata/sunny1")
+	if err != nil {
+		t.Fatal("Couldn't prepare data for testing")
+	}
+
+	PopulateTree("./testdata/sunny1", "./testdata/sunny2", []string{})
+}
+
+func TestMissingOptions(t *testing.T) {
+	err := os.Remove("./testdata/sunny1")
+	if err != nil {
+	}
+	err = os.Remove("./testdata/sunny2")
+	if err != nil {
+	}
+	err = cp.Copy("./testdata/sunny", "./testdata/sunny1")
+	if err != nil {
+		t.Fatal("Couldn't prepare data for testing")
+	}
+
+	PopulateTree("./testdata/sunny1", "./testdata/sunny2", []string{"option1", "option2"})
+}