-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move files/folders to trash bin instead of delete them directly.
- Loading branch information
Showing
6 changed files
with
224 additions
and
29 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
//go:build !windows | ||
// +build !windows | ||
|
||
package explorer | ||
|
||
import ( | ||
"errors" | ||
"os" | ||
"path/filepath" | ||
"runtime" | ||
) | ||
|
||
func throwToTrash(path string) error { | ||
trashDir, err := getTrashFolder() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
absPath, err := filepath.Abs(path) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = os.Stat(absPath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
trashPath := filepath.Join(trashDir, filepath.Base(path)) | ||
err = os.Rename(absPath, trashPath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func getTrashFolder() (string, error) { | ||
switch runtime.GOOS { | ||
case "darwin", "ios": | ||
return appleTrashDir() | ||
default: | ||
return unixTrashDir() | ||
} | ||
} | ||
|
||
// According to Freedesktop.org specifications, the "home trash" directory | ||
// is at $XDG_DATA_HOME/Trash, and $XDG_DATA_HOME in turn defaults to $HOME/.local/share. | ||
// Refs: https://specifications.freedesktop.org/basedir-spec/latest/ | ||
func unixTrashDir() (string, error) { | ||
if xdgHome := os.Getenv("XDG_DATA_HOME"); xdgHome != "" { | ||
trashDir := filepath.Join(xdgHome, "Trash") | ||
err := checkDirExists(trashDir) | ||
if err != nil { | ||
return "", err | ||
} | ||
return trashDir, nil | ||
} | ||
|
||
home, err := os.UserHomeDir() | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
trashDir := filepath.Join(home, ".local/share/Trash") | ||
err = checkDirExists(trashDir) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return trashDir, nil | ||
} | ||
|
||
func appleTrashDir() (string, error) { | ||
dir, err := os.UserHomeDir() | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
trashDir := filepath.Join(dir, ".Trash") | ||
err = checkDirExists(trashDir) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return trashDir, nil | ||
} | ||
|
||
func checkDirExists(dir string) error { | ||
stat, err := os.Stat(dir) | ||
if errors.Is(err, os.ErrNotExist) { | ||
err := os.MkdirAll(dir, os.ModeDir) | ||
if err != nil { | ||
return err | ||
} | ||
} else { | ||
return err | ||
} | ||
|
||
if !stat.IsDir() { | ||
return errors.New("Trash dir is not a folder") | ||
} | ||
|
||
return nil | ||
|
||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
//go:build windows | ||
// +build windows | ||
|
||
package explorer | ||
|
||
import ( | ||
"fmt" | ||
"path/filepath" | ||
"syscall" | ||
"unsafe" | ||
|
||
"golang.org/x/sys/windows" | ||
) | ||
|
||
// The code in this file are mostly credited to the authors of | ||
// https://github.com/Kei-K23/trashbox/blob/main/trashbox_windows.go. | ||
|
||
const ( | ||
FO_DELETE = 3 // File operation: delete | ||
FOF_ALLOWUNDO = 0x40 // Allow to move to Recycle Bin | ||
FOF_NOCONFIRMATION = 0x10 // No confirmation dialog | ||
) | ||
|
||
// SHFILEOPSTRUCT represents the structure used in SHFileOperationW. | ||
type SHFILEOPSTRUCT struct { | ||
WFunc uint32 | ||
PFrom *uint16 | ||
PTo *uint16 | ||
FFlags uint16 | ||
AnyOps bool | ||
HNameMap uintptr | ||
LpszProgressTitle *uint16 | ||
} | ||
|
||
var ( | ||
shell32 = syscall.NewLazyDLL("shell32.dll") | ||
procSHFileOperationW = shell32.NewProc("SHFileOperationW") | ||
) | ||
|
||
func shFileOperation(op *SHFILEOPSTRUCT) error { | ||
ret, _, _ := procSHFileOperationW.Call(uintptr(unsafe.Pointer(op))) | ||
if ret != 0 { | ||
return fmt.Errorf("failed to move file to Recycle Bin, error code: %d", ret) | ||
} | ||
return nil | ||
} | ||
|
||
// throwToTrash moves the specified file or directory to the Windows Recycle Bin. | ||
// | ||
// This function takes the path of a file or directory as an argument, | ||
// converts it to an absolute path, and then moves it to the Windows | ||
// Recycle Bin using the Shell API. If the provided path does not | ||
// exist or cannot be accessed, an error will be returned. | ||
// | ||
// The function uses the SHFileOperationW function from the Windows | ||
// Shell API to perform the move operation. It sets the appropriate | ||
// flags to allow undo and suppress confirmation dialogs. If the | ||
// operation is successful, the file or directory will no longer exist | ||
// at the original path and will be relocated to the Recycle Bin for | ||
// potential recovery. | ||
// | ||
// Parameters: | ||
// - path: The path of the file or directory to be moved to the | ||
// Recycle Bin. | ||
// | ||
// Returns: | ||
// - error: Returns nil on success. If an error occurs during the | ||
// process (e.g., if the file does not exist or the move fails), | ||
// an error will be returned explaining the reason for failure, | ||
// including any relevant error codes from the Windows API. | ||
func throwToTrash(path string) error { | ||
// Get the absolute file path of delete file | ||
absPath, err := filepath.Abs(path) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
wPathPtr, err := windows.UTF16PtrFromString(absPath + "\x00") | ||
if err != nil { | ||
return err | ||
} | ||
|
||
op := &SHFILEOPSTRUCT{ | ||
WFunc: FO_DELETE, | ||
PFrom: wPathPtr, | ||
FFlags: FOF_ALLOWUNDO | FOF_NOCONFIRMATION, | ||
} | ||
|
||
return shFileOperation(op) | ||
} |
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
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
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