package main import ( "bufio" "flag" "fmt" "io" "os" "os/exec" "regexp" ) var ( EnvFilePath = flag.String("f", ".env", "environment file") EnvVarRegex = regexp.MustCompile(`^(.*?)=(.*?)$`) EnvCommentRegex = regexp.MustCompile(`^[ \t]*#.*?$`) ) func main() { flag.Parse() envFile, err := os.Open(*EnvFilePath) if err != nil { fmt.Fprintf(os.Stderr, "could not open file '%s': %s\n", *EnvFilePath, err.(*os.PathError).Err) return } defer envFile.Close() parseEnvFile(envFile) args := flag.Args() if len(args) == 0 { for _, envVar := range os.Environ() { fmt.Println(envVar) } return } cmd := exec.Command(args[0], args[1:]...) cmd.Env = os.Environ() cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { if exitErr, ok := err.(*exec.ExitError); ok { os.Exit(exitErr.ExitCode()) return } else { panic(err) } } } func parseEnvFile(r io.Reader) { s := bufio.NewScanner(r) l := 0 for s.Scan() { l++ matches := EnvVarRegex.FindStringSubmatch(s.Text()) if len(matches) != 0 { key, value := matches[1], os.ExpandEnv(matches[2]) os.Setenv(key, value) } else if s.Text() != "" && !EnvCommentRegex.MatchString(s.Text()) { panic(fmt.Sprintf("invalid env syntax on line %d", l)) } } }