@@ 0,0 1,105 @@
+package main
+
+import (
+ "errors"
+ "flag"
+ "fmt"
+ "io/fs"
+ "os"
+)
+
+const ModeUserWrite = 0o200
+
+func main() {
+ var recursive bool
+ var force bool
+ var rmdir bool
+ var help bool
+
+ flag.BoolVar(&recursive, "r", false, "recursive")
+ flag.BoolVar(&recursive, "recursive", false, "recursive")
+ flag.BoolVar(&force, "f", false, "force")
+ flag.BoolVar(&force, "force", false, "force")
+ flag.BoolVar(&rmdir, "d", false, "rmdir")
+ flag.BoolVar(&rmdir, "dir", false, "rmdir")
+ flag.BoolVar(&help, "h", false, "help")
+ flag.BoolVar(&help, "help", false, "help")
+ flag.Parse()
+
+ if help {
+ fmt.Println(`Usage: rm [OPTION]... [FILE]...
+Remove (unlink) the FILE(s).
+
+ -f, --force ignore nonexistent files and arguments, never prompt
+ -r, --recursive remove directories and their contents recursively
+ -d, --dir remove empty directories
+ --help display this help and exit
+
+By default, rm does not remove directories. Use the --recursive (-r)
+option to remove each listed directory, too, along with all of its contents.`)
+ os.Exit(0)
+ }
+
+ if flag.NArg() < 1 {
+ fmt.Println("rm: missing operand")
+ fmt.Println("Try \"rm --help\" for more information.")
+ os.Exit(1)
+ }
+
+ for _, f := range flag.Args() {
+ fi, serr := os.Stat(f)
+ if serr != nil {
+ if errors.Is(serr, fs.ErrNotExist) {
+ fmt.Fprintf(os.Stderr, "rm: cannot remove %q: no such file or directory\n", f)
+ } else {
+ fmt.Fprintf(os.Stderr, "rm: cannot remove %q: %w\n", f, serr)
+ }
+ os.Exit(1)
+ }
+
+ // write-protected
+ if fi.Mode().Perm()&ModeUserWrite == 0 {
+ var propstring string
+ if fi.Mode().IsRegular() {
+ propstring += "regular "
+ }
+ if fi.Size() == 0 {
+ propstring += "empty "
+ }
+
+ fmt.Fprintf(os.Stderr, "rm: remove write-protected %sfile %q? ", propstring, f)
+ var response string
+ fmt.Scanln(&response)
+ if response != "y" {
+ os.Exit(0)
+ }
+ }
+
+ if fi.IsDir() {
+ if rmdir {
+ if err := os.Remove(f); err != nil {
+ if pe, ok := err.(*fs.PathError); ok {
+ fmt.Fprintf(os.Stderr, "rm: cannot remove %q: %s\n", f, pe.Err.Error())
+ } else {
+ fmt.Fprintf(os.Stderr, "rm: cannot remove %q: %s\n", f, err.Error())
+ }
+ os.Exit(1)
+ }
+ }
+ if !recursive {
+ fmt.Fprintf(os.Stderr, "rm: cannot remove %q: is a directory\n", f)
+ os.Exit(1)
+ } else {
+ if rerr := os.RemoveAll(f); rerr != nil {
+ fmt.Fprintln(os.Stderr, rerr.Error())
+ os.Exit(1)
+ }
+ }
+ } else {
+ if err := os.Remove(f); err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ }
+ }
+}