docs/v3/path-and-walk.md
Command.Path() returns the list of command names from the root to the
current command. Command.Walk() visits a command and every subcommand
recursively, calling a function on each.
The Path() method returns []string where each element is a Command.Name
starting from the root. FullName() is equivalent to
strings.Join(cmd.Path(), " ").
package main
import (
"context"
"fmt"
"os"
"github.com/urfave/cli/v3"
)
func main() {
subSubCmd := &cli.Command{Name: "bottom", Action: func(context.Context, *cli.Command) error { return nil }}
subCmd := &cli.Command{Name: "mid", Subcommands: []*cli.Command{subSubCmd}, Action: func(context.Context, *cli.Command) error { return nil }}
cmd := &cli.Command{
Name: "top",
Subcommands: []*cli.Command{subCmd},
Action: func(ctx context.Context, c *cli.Command) error {
fmt.Println(strings.Join(c.Path(), " "))
return nil
},
}
cmd.Run(context.Background(), []string{"top", "mid", "bottom"})
}
$ go run .
top mid bottom
Walk() traverses the command tree depth-first, visiting the command itself
first, then each subcommand recursively.
package main
import (
"context"
"fmt"
"os"
"github.com/urfave/cli/v3"
)
func main() {
subSubCmd := &cli.Command{Name: "bottom", Action: func(context.Context, *cli.Command) error { return nil }}
subCmd := &cli.Command{Name: "mid", Subcommands: []*cli.Command{subSubCmd}, Action: func(context.Context, *cli.Command) error { return nil }}
cmd := &cli.Command{
Name: "top",
Subcommands: []*cli.Command{subCmd},
Action: func(ctx context.Context, c *cli.Command) error { return nil },
}
cmd.Walk(func(c *cli.Command) error {
fmt.Println(c.Name)
return nil
})
}
$ go run .
top
mid
bottom
Return a non-nil error from the walk function to stop traversal early.
<!-- { "output": "top\nmid" } -->package main
import (
"errors"
"fmt"
"os"
"github.com/urfave/cli/v3"
)
func main() {
subSubCmd := &cli.Command{Name: "bottom", Action: func(context.Context, *cli.Command) error { return nil }}
subCmd := &cli.Command{Name: "mid", Subcommands: []*cli.Command{subSubCmd}, Action: func(context.Context, *cli.Command) error { return nil }}
cmd := &cli.Command{
Name: "top",
Subcommands: []*cli.Command{subCmd},
Action: func(ctx context.Context, c *cli.Command) error { return nil },
}
err := cmd.Walk(func(c *cli.Command) error {
fmt.Println(c.Name)
if c.Name == "mid" {
return errors.New("stop")
}
return nil
})
fmt.Println(err)
}
$ go run .
top
mid
stop
Lineage()
returns the command and all its ancestors as []*Command (child first).
Path() is similar but returns only the command names as []string (root
first). Use Lineage() when you need access to the ancestor *Command
values; use Path() when you only need the names.