ExecForEach renders cmdLine as a Go template for each line of input, running the resulting command, and produces the combined output of all these commands in sequence. See [Pipe.Exec] for details on error handling and environment variables. This is mostly useful for substituting data into commands
(cmdLine string)
| 463 | // |
| 464 | // ListFiles("*").ExecForEach("touch {{.}}").Wait() |
| 465 | func (p *Pipe) ExecForEach(cmdLine string) *Pipe { |
| 466 | tpl, err := template.New("").Parse(cmdLine) |
| 467 | if err != nil { |
| 468 | return p.WithError(err) |
| 469 | } |
| 470 | return p.Filter(func(r io.Reader, w io.Writer) error { |
| 471 | scanner := newScanner(r) |
| 472 | for scanner.Scan() { |
| 473 | cmdLine := new(strings.Builder) |
| 474 | err := tpl.Execute(cmdLine, scanner.Text()) |
| 475 | if err != nil { |
| 476 | return err |
| 477 | } |
| 478 | args, err := shell.Fields(cmdLine.String(), nil) |
| 479 | if err != nil { |
| 480 | return err |
| 481 | } |
| 482 | cmd := exec.Command(args[0], args[1:]...) |
| 483 | cmd.Stdout = w |
| 484 | cmd.Stderr = w |
| 485 | pipeStderr := p.stdErr() |
| 486 | if pipeStderr != nil { |
| 487 | cmd.Stderr = pipeStderr |
| 488 | } |
| 489 | if p.env != nil { |
| 490 | cmd.Env = p.env |
| 491 | } |
| 492 | err = cmd.Start() |
| 493 | if err != nil { |
| 494 | fmt.Fprintln(cmd.Stderr, err) |
| 495 | continue |
| 496 | } |
| 497 | err = cmd.Wait() |
| 498 | if err != nil { |
| 499 | fmt.Fprintln(cmd.Stderr, err) |
| 500 | continue |
| 501 | } |
| 502 | } |
| 503 | return scanner.Err() |
| 504 | }) |
| 505 | } |
| 506 | |
| 507 | var exitStatusPattern = regexp.MustCompile(`exit status (\d+)$`) |
| 508 |