@@ -39,6 +39,7 @@ require (
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef
github.com/stretchr/testify v1.10.0
github.com/tidwall/sjson v1.2.5
+ github.com/u-root/u-root v0.14.1-0.20250722142936-bf4e78a90dfc
github.com/zeebo/xxh3 v1.0.2
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394
gopkg.in/natefinch/lumberjack.v2 v2.2.1
@@ -108,7 +109,7 @@ require (
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/sethvargo/go-retry v0.3.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
- github.com/spf13/pflag v1.0.6 // indirect
+ github.com/spf13/pflag v1.0.7 // indirect
github.com/tetratelabs/wazero v1.9.0 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
@@ -234,8 +234,9 @@ github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
-github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
+github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE=
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
@@ -258,6 +259,8 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
+github.com/u-root/u-root v0.14.1-0.20250722142936-bf4e78a90dfc h1:HjI/UCF4dRyzizePQrhGUSQvuU7z4tOqMqz6GRGlFCM=
+github.com/u-root/u-root v0.14.1-0.20250722142936-bf4e78a90dfc/go.mod h1:/0Qr7qJeDwWxoKku2xKQ4Szc+SwBE3g9VE8jNiamsmc=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
@@ -0,0 +1,59 @@
+package shell
+
+import (
+ "context"
+
+ "github.com/u-root/u-root/pkg/core"
+ "github.com/u-root/u-root/pkg/core/cat"
+ "github.com/u-root/u-root/pkg/core/chmod"
+ "github.com/u-root/u-root/pkg/core/cp"
+ "github.com/u-root/u-root/pkg/core/find"
+ "github.com/u-root/u-root/pkg/core/ls"
+ "github.com/u-root/u-root/pkg/core/mkdir"
+ "github.com/u-root/u-root/pkg/core/mv"
+ "github.com/u-root/u-root/pkg/core/rm"
+ "github.com/u-root/u-root/pkg/core/touch"
+ "github.com/u-root/u-root/pkg/core/xargs"
+ "mvdan.cc/sh/v3/interp"
+)
+
+var coreUtils = map[string]func() core.Command{
+ "cat": func() core.Command { return cat.New() },
+ "chmod": func() core.Command { return chmod.New() },
+ "cp": func() core.Command { return cp.New() },
+ "find": func() core.Command { return find.New() },
+ "ls": func() core.Command { return ls.New() },
+ "mkdir": func() core.Command { return mkdir.New() },
+ "mv": func() core.Command { return mv.New() },
+ "rm": func() core.Command { return rm.New() },
+ "touch": func() core.Command { return touch.New() },
+ "xargs": func() core.Command { return xargs.New() },
+}
+
+func (s *Shell) coreUtilsHandler() func(next interp.ExecHandlerFunc) interp.ExecHandlerFunc {
+ return func(next interp.ExecHandlerFunc) interp.ExecHandlerFunc {
+ return func(ctx context.Context, args []string) error {
+ if len(args) == 0 {
+ return next(ctx, args)
+ }
+
+ program, programArgs := args[0], args[1:]
+
+ newCoreUtil, ok := coreUtils[program]
+ if !ok {
+ return next(ctx, args)
+ }
+
+ c := interp.HandlerCtx(ctx)
+
+ cmd := newCoreUtil()
+ cmd.SetIO(c.Stdin, c.Stdout, c.Stderr)
+ cmd.SetWorkingDir(c.Dir)
+ cmd.SetLookupEnv(func(key string) (string, bool) {
+ v := c.Env.Get(key)
+ return v.Str, v.Set
+ })
+ return cmd.RunContext(ctx, programArgs...)
+ }
+ }
+}
@@ -221,7 +221,7 @@ func (s *Shell) execPOSIX(ctx context.Context, command string) (string, string,
interp.Interactive(false),
interp.Env(expand.ListEnviron(s.env...)),
interp.Dir(s.cwd),
- interp.ExecHandlers(s.blockHandler()),
+ interp.ExecHandlers(s.blockHandler(), s.coreUtilsHandler()),
)
if err != nil {
return "", "", fmt.Errorf("could not run command: %w", err)