update to the unpacker, delete the archives when unpacking completes; it works but I think it has a few bugs.

in Programming & Dev4 months ago

In my previous post in this community Here
I wrote about a small program I had written to extract archives, and this was all the program did. I was not entirely happy with this. Though I did not go and write something that crawls all folders and extract everything.
I added a nice addition to it, well I say added, I really just rewrote the thing, which is fortunately easy when the program is only less than 100 lines long.

The addition I made to the program is that I want it to be able to remove the archive when it is extracted, this sounds easy, but actually it isn't always a simple thing. While it is not super difficult it is not easy as such.
There might be archives that span several files (part1 part2 part3) and I want my program to find all these parts of the archive.

In fact finding all the parts of the archive was the problem I had to solve, I think I did a reasonable job.
As the last version this was written in go, as that is my go to language for simple stuff.

package main

import (
    "flag"
    "fmt"
    "os"
    "os/exec"
    "regexp"
    "strings"
)


func main() {
    path_ptr := flag.String("path", "", "Full path to the file")
    flag.Parse()
    var delete []string
    parts := strings.Split(*path_ptr, "/")
    parts_len := len(parts)
    filename := parts[parts_len-1]
    basepath := strings.Join(parts[0:parts_len-1], "/")
    partre, err := regexp.Compile(`([a-zA-Z-]+)(\.|-)\w+(\d+)`)
    if err != nil {
        panic(err)
    }
    part_match := partre.FindAllStringSubmatch(filename, -1)
    fmt.Println(part_match)
    files, ferr := os.ReadDir(basepath)
    if ferr != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    for _, file := range files {
        file_match := partre.FindAllStringSubmatch(file.Name(), -1)
        if file_match == nil {
            break
        }
        if file_match[0][1] == part_match[0][1] {
            fname := fmt.Sprintf("%s/%s", basepath, file.Name())
            delete = append(delete, fname)
        }
    }
    extractArchive(filename, basepath)
    for _, file := range delete {
        deleteFile(file, basepath)
    }
}

func extractArchive(f string, dir string) {
    end_re, err := regexp.Compile(`.\w+$`)
    if err != nil {
        panic(err)
    }
    ending := end_re.FindAllStringSubmatch(f, -1)
    var cmd *exec.Cmd
    if ending[0][0] == ".rar" {
        cmd = exec.Command("unrar", "x", f)
        cmd.Dir = dir
    }
    cmd.Run()
}

func deleteFile(f string, dir string) {
    cmd := exec.Command("rm", f)
    cmd.Dir = dir
    cmd.Run()
}

This is the whole program.

    parts := strings.Split(*path_ptr, "/")
    parts_len := len(parts)
    filename := parts[parts_len-1]

This is necessary since I think go does not have the negative index, it is a shame, but not really a big deal.
if go had the negative indexes it could be written as

    filename := parts[-1]

but then parts is still useful for the basename, so it is not that big a deal in this case.
If there is a way to do negative indexes in go, I would like to know.

    file_match := partre.FindAllStringSubmatch(file.Name(), -1)
    if file_match == nil {
        break
    }

This is just checking saying that if the match didn't find anything break out of the loop, this actually is likely a bug waiting to happen. Since it might break before anything is found. Note to self fix this bug.
It should be simple to fix it, use continue instead of break, then it will go over all cases but won't complain about lacking indexes.

There is a regex that matches the end, and the base name, such that I can find other cases. And actually this could be a case where I have another bug, but this one is not going to be as easy to fix.

Ideally I have some bugs to fix to post an update later.

Also the way this program works is a bit brittle.

Well for my next part I will see if I can fix all the bugs.
In case you find other problems please do leave a comment below.