From d6efbd22fd0a3cae6f2899a35ac43c49eaf39525 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Fri, 21 Nov 2025 16:44:31 -0800 Subject: [PATCH] add bcuz --- cmd/bcuz/README | 8 ++++ cmd/bcuz/main.go | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 cmd/bcuz/README create mode 100644 cmd/bcuz/main.go diff --git a/cmd/bcuz/README b/cmd/bcuz/README new file mode 100644 index 0000000..6066db5 --- /dev/null +++ b/cmd/bcuz/README @@ -0,0 +1,8 @@ +bcuz: bandcamp unzip + +When you download stuff from bandcamp, it gives you a zip file that +extracts files into the current directory. This is a quick hack tries +to parse the filename as "artist - album", unpack the contents to +"artist/album/*", and remove the zip file (which can be kept with +-k). Works on my machineā„¢, good enough for me. + diff --git a/cmd/bcuz/main.go b/cmd/bcuz/main.go new file mode 100644 index 0000000..3dccf25 --- /dev/null +++ b/cmd/bcuz/main.go @@ -0,0 +1,99 @@ +package main + +import ( + "archive/zip" + "flag" + "fmt" + "io" + "os" + "path/filepath" + "strings" +) + +var keepArchive bool + +func removedir(dir string, existed bool) { + if !existed { + os.RemoveAll(dir) + } +} + +func unpackFile(path string) error { + var dir string + var existed bool + + fmt.Printf("[+] processing %s:\n", path) + + base := filepath.Base(path[:len(path)-4]) + pieces := strings.SplitN(base, "-", 2) + if len(pieces) == 2 { + artist := strings.TrimSpace(pieces[0]) + album := strings.TrimSpace(pieces[1]) + dir = filepath.Join(artist, album) + } else { + dir = base + } + + _, err := os.Stat(dir) + if err == nil { + existed = true + } + + fmt.Printf("\tunpack directory: %s\n", dir) + err = os.MkdirAll(dir, 0755) + if err != nil { + return err + } + + r, err := zip.OpenReader(path) + if err != nil { + removedir(dir, existed) + return err + } + defer r.Close() + + var rc io.ReadCloser + for _, f := range r.File { + fmt.Printf("\tunpacking %s\n", f.FileHeader.Name) + rc, err = f.Open() + if err != nil { + rc.Close() + removedir(dir, existed) + return err + } + + out, err := os.Create(filepath.Join(dir, f.FileHeader.Name)) + if err != nil { + rc.Close() + removedir(dir, existed) + return err + } + + _, err = io.Copy(out, rc) + if err != nil { + rc.Close() + removedir(dir, existed) + return err + } + + out.Close() + rc.Close() + } + + if !keepArchive { + return os.Remove(path) + } + return nil +} + +func main() { + flag.BoolVar(&keepArchive, "k", false, "don't remove the archive file after unpacking") + flag.Parse() + + for _, path := range flag.Args() { + err := unpackFile(path) + if err != nil { + fmt.Fprintf(os.Stderr, "[!] failed to process %s: %s\n", path, err) + } + } +}