Skip to content

Instantly share code, notes, and snippets.

@NathBabs
Created July 19, 2023 09:09
Show Gist options
  • Save NathBabs/2fd500eb82f93f90bc981f0033d20ad8 to your computer and use it in GitHub Desktop.
Save NathBabs/2fd500eb82f93f90bc981f0033d20ad8 to your computer and use it in GitHub Desktop.
Cleanup a folder by arranging files into their appropraite folders. Run by passing in the path to the folder it should clean e.g ` go run cleanup.go ~/Downloads/test`
package main
import (
"fmt"
"os"
"path/filepath"
)
// crate a map of file extensions to folders
// folderMap := make(map[string]string)
var folderMap = map[string]string{
".txt": "TextFiles",
".doc": "Documents",
".docx": "Documents",
".pdf": "Documents",
".zip": "Compressed",
".gz": "Compressed",
".jpg": "Pictures",
".jpeg": "Pictures",
".png": "Pictures",
".mp4": "Videos",
".mkv": "Videos",
".mov": "Videos",
".mp3": "Music",
".app": "Apps",
".dmg": "Apps",
".pkg": "Apps",
".srt": "Videos",
}
// create slice to hold file extensions that could not be handled
var unhandledExtensions []string
// create a function that takes in a folder path from the command line
// verify it's a folder
// go run cleanup.go ~/Users/josh/Desktop/test
func cleanup(path string) (bool, error) {
_, err := IsDirectory(path)
if err != nil {
fmt.Printf("Path at: %v is not a directory please input a path to a file ", path)
return false, err
}
// read the directory
dir, err := os.Open(path)
if err != nil {
fmt.Println("Error opening directory:", err)
}
// read the directory
files, err := dir.Readdir(-1)
if err != nil {
fmt.Println("Unable to read directory:", err)
}
for _, file := range files {
// get file extension of a file
fileExt := filepath.Ext(file.Name())
// check if file is also a directory
if (fileExt == "" || fileExt == ".DS_Store") || file.IsDir() {
fmt.Println("File has no extension or is a directory")
continue
}
// get file extension from map and create appropariate folder
folder, found := folderMap[fileExt]
if !found {
msg := fmt.Sprintf("Sorry can not handle this file extension: %v", fileExt)
//fmt.Fprintf(os.Stderr, "Sorry can not handle this file extension: %v", fileExt) //rintf("Sorry can not handle this file extension: %v", fileExt)
fmt.Println(msg)
// after printing the error, continue to the next file
// add file extension to unhandledExtensions
unhandledExtensions = append(unhandledExtensions, fileExt)
continue
}
// os.Mkdir(folderPath, os.ModePerm)
// check if Folder exists in directory, if not create
folderPath := filepath.Join(path, folder)
fmt.Println("folderPath is :", folderPath)
// check if folder exists, if not create
// then move file to folder
_, err = os.Stat(folderPath)
if err != nil {
if errDir := os.Mkdir(folderPath, os.ModePerm); errDir != nil {
// stop loop and stop program
fmt.Println("Error creating folder:", err)
return false, errDir
}
}
fmt.Println("Folder now exists")
// move the file to the newly created folder
oldFilePath := filepath.Join(path, file.Name())
newFilePath := filepath.Join(folderPath, file.Name())
// print to the terminal, "moving {file.Name} to {newFolderPath}"
fmt.Printf("Moving %v to %v\n......", file.Name(), folderPath)
// change permission of file, so that it can be moved
err = os.Chmod(oldFilePath, 0777)
if err != nil {
fmt.Println("Error changing file permission:", err)
os.Exit(1)
}
err = os.Rename(oldFilePath, newFilePath)
if err != nil {
fmt.Println("Error moving file:", err)
os.Exit(1)
}
// print to the terminal, "done moving to {newFolderPath}"
fmt.Println("done moving to", folderPath)
}
// close the folder
defer dir.Close()
// print unhandledExtensions, if slice is not empty
if len(unhandledExtensions) > 0 {
fmt.Println("Could not handle these file extensions: ", unhandledExtensions)
}
return true, nil
}
func IsDirectory(path string) (bool, error) {
fileInfo, err := os.Stat(path)
if err != nil {
return false, err
}
return fileInfo.IsDir(), err
}
func main() {
// get the path from the user
path := os.Args[1]
// call the cleanup function with the path
_, err := cleanup(path)
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
}
@Iyusuf40
Copy link

Nice work boss, I've got some lil suggestions..

  1. At line 60: if file is directory, except '.' and '..' directories, it would be nice if you could recursively go down the directory and clean the files there
  2. At line 89: suppose you have already moved some files and then you got this point, if you return you would have done only some of the work and left the rest, personally I'd prefer using 'continue' there so you could skip the problematic file and finish the rest.

Once again, nice work, at some point in the future I'd love to learn golang

@NathBabs
Copy link
Author

NathBabs commented Jul 19, 2023

Nice work boss, I've got some lil suggestions..

1. At line 60: if file is directory, except '.' and  '..' directories, it would be nice if you could recursively go down the directory and clean the files there

2. At line 89: suppose you have already moved some files and then you got this point, if you return you would have done only some of the work and left the rest, personally I'd prefer using 'continue' there so you could skip the problematic file and finish the rest.

Once again, nice work, at some point in the future I'd love to learn golang

@lyusuf40 Regarding your first point, for a program that does one thing, it's better it doesn't do any recursive task. If it should be recursive, then I believe it should be specified by the user, so that can be an added option , and probably take in a flag via the command line to indicate that e.g -r , and I'll check for this flag in the code.

Then for your second point, that's true I actually contemplated it. I could probably create a slice to hold the folders that couldn't be created and print it to the user after the process is done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment