Help us shape the future of Go! Take the 2026 Go Developer Survey

files

package
v0.25.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2025 License: MIT Imports: 10 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var FilesCmd = &cobra.Command{
	Use:   "files",
	Short: "A command for managing files",
	Long:  `This command will help manage various aspects of file operations on MacOS and Linux systems.`,
	Run: func(cmd *cobra.Command, args []string) {
		err := cmd.Help()
		cobra.CheckErr(err)
	},
}
View Source
var FindAndDeleteCmd = &cobra.Command{
	Use:   "findAndDelete [directory]",
	Short: "Find and delete files of selected types",
	Long: `Recursively scan the provided directory for files of types selected by the user
and delete them after an interactive confirmation. Starts with JSON files; more
types (movies, images, etc.) will be added later.
`,
	Args: cobra.ExactArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		dir := args[0]
		isVerbose := utils.IsVerbose(cmd)

		if _, err := os.Stat(dir); os.IsNotExist(err) {
			log.Error("Provided directory does not exist: %s", dir)
			return
		}

		matchFn, err := buildMatchFunction(globPattern, extension)
		if err != nil {
			log.Error("Error building match function: %v", err)
			return
		}
		if matchFn == nil {

			options := []string{"JSON (.json)"}
			var selected []string
			prompt := &survey.MultiSelect{
				Message: "Select file types to find and delete:",
				Options: options,
			}
			if err := survey.AskOne(prompt, &selected); err != nil {
				log.Error("Error collecting selection: %v", err)
				return
			}

			if len(selected) == 0 {
				log.Info("No file types selected. Nothing to do.")
				return
			}

			extLookup := map[string]bool{}
			for _, s := range selected {
				s = strings.ToLower(s)
				if strings.Contains(s, "json") {
					extLookup[".json"] = true
				}

			}
			matchFn = func(name string) bool {
				return extLookup[strings.ToLower(filepath.Ext(name))]
			}
		}

		log.Start("Scanning for files...")
		spinner := utils.NewProgressSpinner("Scanning directories...")
		matches, totalSize, walkErr := ScanFiles(dir, matchFn, spinner)

		if walkErr != nil {
			spinner.Stop()
			log.Error("Error scanning directory: %v", walkErr)
			return
		}

		spinner.UpdateMessage("Scan complete.")
		spinner.SetProgressBar(1.0)
		spinner.Stop()

		if walkErr != nil {
			log.Error("Error scanning directory: %v", walkErr)
			return
		}

		if len(matches) == 0 {
			log.Success("No matching files found in %s.", dir)
			return
		}

		log.Message("\nFound %d file(s) (%.2f MB total):", len(matches), float64(totalSize)/(1024*1024))
		for _, m := range matches {
			if isVerbose {
				log.Message("  - %s", m)
			} else {
				log.Message("  - %s", filepath.Base(m))
			}
		}

		confirm := false
		promptConfirm := &survey.Confirm{
			Message: fmt.Sprintf("Delete %d file(s) (%.2f MB)?", len(matches), float64(totalSize)/(1024*1024)),
			Default: false,
		}
		if err := survey.AskOne(promptConfirm, &confirm); err != nil {
			log.Error("Error during confirmation prompt: %v", err)
			return
		}
		if !confirm {
			log.Info("Deletion cancelled by user.")
			return
		}

		// Attempt parallel deletion
		var deleted, errors atomic.Int64
		var wg sync.WaitGroup
		workerCount := 4
		fileChan := make(chan string, len(matches))

		for i := 0; i < workerCount; i++ {
			wg.Add(1)
			go func() {
				defer wg.Done()
				for f := range fileChan {
					if f == "" {
						continue
					}
					if err := os.Remove(f); err != nil {
						if !os.IsNotExist(err) {
							log.Error("Failed to delete %s: %v", f, err)
							errors.Add(1)
						}
					} else {
						if isVerbose {
							log.Success("Deleted %s", f)
						}
						deleted.Add(1)
					}
				}
			}()
		}

		for _, f := range matches {
			fileChan <- f
		}
		close(fileChan)

		wg.Wait()

		log.Success("Done. Deleted %d file(s), %d errors.", deleted.Load(), errors.Load())
	},
}

Functions

func ScanFiles

func ScanFiles(dir string, matchFn func(name string) bool, spinner *utils.Spinner) ([]string, int64, error)

Types

type FileTypeCategory

type FileTypeCategory struct {
	Name       string
	Extensions map[string]bool
	Options    []string // For display in the survey
}

FileTypeCategory represents a category of file types with their extensions

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL