You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
176 lines
3.4 KiB
176 lines
3.4 KiB
//go:binary-only-package
|
|
package main
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"path/filepath"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"strings"
|
|
//"log"
|
|
"os"
|
|
"sync"
|
|
"strconv"
|
|
)
|
|
|
|
var keepLongExt bool = false
|
|
var fake bool = false
|
|
var recurse bool = false
|
|
var noErr bool = false
|
|
|
|
func last(str []string) string {
|
|
if(len(str)<1) {
|
|
return ""
|
|
} else {
|
|
return fmt.Sprintf(".%s", str[len(str)-1])
|
|
}
|
|
}
|
|
|
|
func hash(file string) []byte {
|
|
f, err := os.Open(file)
|
|
if err != nil {
|
|
fmt.Printf("E: Cannot open file: %s", err);
|
|
}
|
|
defer f.Close()
|
|
|
|
h := sha256.New()
|
|
if _, err := io.Copy(h, f); err != nil {
|
|
fmt.Printf("E: Cannot create hash: %s", err);
|
|
}
|
|
|
|
return h.Sum(nil)
|
|
}
|
|
|
|
func extractExt(x string) string {
|
|
if (keepLongExt) {
|
|
return last(strings.SplitN(x, ".", 2)[1:])
|
|
} else {
|
|
return filepath.Ext(x)
|
|
}
|
|
}
|
|
|
|
func dofile(i int, y string) {
|
|
loc, x := filepath.Split(y)
|
|
sha := hash(y)
|
|
str := fmt.Sprintf("%x", sha)
|
|
newname := fmt.Sprintf("%s%s%s", loc, str, extractExt(x))
|
|
if _, err := os.Stat(newname); !os.IsNotExist(err) {
|
|
if(!noErr) {
|
|
fmt.Printf("E: (%d) %s: %s alread exists.\n", i, y, newname)
|
|
}
|
|
} else {
|
|
if !fake {
|
|
os.Rename(y,newname)
|
|
}
|
|
fmt.Printf("(%d) %s -> %s\n", i, y, newname)
|
|
}
|
|
}
|
|
var maxThreads int = 0
|
|
func main() {
|
|
ar := os.Args[1:];
|
|
var wg sync.WaitGroup
|
|
|
|
if (len(ar) < 1) {
|
|
fmt.Printf("Usage: %s [--long] [--fake] [--recurse] [-quiet] [--threads <number>] <file ...>\n\t--long\tKeep long file extensions\n\t--fake\tDo not rename files.\n\t--recurse\tWalk path recursively.\n\t--quiet\tDo not show (some) errors.\n", os.Args[0])
|
|
return;
|
|
}
|
|
var ignore = false
|
|
for i, x := range ar {
|
|
if ignore {
|
|
ignore=false
|
|
continue
|
|
}
|
|
if( strings.HasPrefix(x, "--")) {
|
|
switch x[2:] {
|
|
case "long":
|
|
keepLongExt = !keepLongExt
|
|
case "fake":
|
|
fake = !fake
|
|
case "recurse":
|
|
recurse = !recurse
|
|
case "quiet":
|
|
noErr = !noErr
|
|
case "threads":
|
|
if i<len(ar)-1 {
|
|
if th, err := strconv.Atoi(ar[i+1]); err ==nil {
|
|
maxThreads = th
|
|
ignore = true
|
|
continue
|
|
} else {
|
|
fmt.Printf("Bad threads flag");
|
|
}
|
|
} else {
|
|
fmt.Printf("No threads flag")
|
|
}
|
|
default:
|
|
fmt.Printf("Unknown flag \"%s\"\n", x)
|
|
}
|
|
} else {
|
|
if fi, err:= os.Stat(x); os.IsNotExist(err) {
|
|
fmt.Printf("(%d) %s does not exist.\n", i, x)
|
|
} else {
|
|
var sem chan bool
|
|
|
|
if maxThreads > 1 {
|
|
sem = make(chan bool, maxThreads)
|
|
} else {
|
|
sem = make(chan bool)
|
|
}
|
|
|
|
var _dofile = func(i int, s string) {
|
|
if maxThreads == 1 {
|
|
dofile(i,s)
|
|
return
|
|
}
|
|
wg.Add(1)
|
|
if(maxThreads>0) {
|
|
sem <- true
|
|
}
|
|
|
|
go func() {
|
|
defer wg.Done()
|
|
dofile(i,s)
|
|
if(maxThreads>0) {
|
|
<-sem
|
|
}
|
|
}()
|
|
}
|
|
|
|
if(fi.Mode().IsDir()) {
|
|
if(recurse) {
|
|
filepath.Walk(x, func(path string, f os.FileInfo, err error) error {
|
|
if(!f.Mode().IsDir()) {
|
|
_dofile(i,path)
|
|
}
|
|
return nil
|
|
})
|
|
} else {
|
|
files, err := ioutil.ReadDir(x)
|
|
if err != nil {
|
|
fmt.Printf("E: Error enumerating files in %s: %s\n", x, err)
|
|
} else {
|
|
for _, f := range files {
|
|
if(!f.Mode().IsDir()) {
|
|
fl := fmt.Sprintf("%s/%s", x, f.Name())
|
|
_dofile(i,fl)
|
|
} else {
|
|
fmt.Printf("!: Ignoring %s (is directory)\n", f.Name())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
|
|
_dofile(i, x)
|
|
}
|
|
close(sem)
|
|
|
|
}
|
|
}
|
|
}
|
|
wg.Wait()
|
|
return;
|
|
|
|
}
|