Created
July 19, 2023 09:09
-
-
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`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
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
Nice work boss, I've got some lil suggestions..
Once again, nice work, at some point in the future I'd love to learn golang