dups: symlink support

this came in handy for my talks repo

Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
This commit is contained in:
Vincent Batts 2018-09-03 21:45:18 -04:00
parent 0d414be0e7
commit d8658e4d1b
Signed by: vbatts
GPG key ID: 10937E57733F1362

View file

@ -17,8 +17,9 @@ import (
var ( var (
flLoadMap = flag.String("l", "", "load existing map from file") flLoadMap = flag.String("l", "", "load existing map from file")
flSaveMap = flag.String("s", "hash-map.json", "file to save map of file hashes to") flSaveMap = flag.String("o", "hash-map.json", "file to save map of file hashes to")
flHardlink = flag.Bool("H", false, "hardlink the duplicate files") flHardlink = flag.Bool("H", false, "hardlink the duplicate files")
flSymlink = flag.Bool("s", false, "symlink the duplicate files")
flQuiet = flag.Bool("q", false, "less output") flQuiet = flag.Bool("q", false, "less output")
nprocs = 1 nprocs = 1
) )
@ -93,11 +94,18 @@ func main() {
fmt.Printf("%q is the same content as %q\n", path, fpath) fmt.Printf("%q is the same content as %q\n", path, fpath)
} }
if *flHardlink { if *flHardlink {
if err = SafeLink(fpath, path); err != nil { if err = SafeLink(fpath, path, true); err != nil {
fmt.Fprintln(os.Stderr, err, path) fmt.Fprintln(os.Stderr, err, path)
return return
} }
fmt.Printf("linked %q to %q\n", path, fpath) fmt.Printf("hard linked %q to %q\n", path, fpath)
}
if *flSymlink {
if err = SafeLink(fpath, path, false); err != nil {
fmt.Fprintln(os.Stderr, err, path)
return
}
fmt.Printf("soft linked %q to %q\n", path, fpath)
} }
savings += info.Size() savings += info.Size()
} else { } else {
@ -135,7 +143,7 @@ func main() {
} }
// SafeLink overrides newname if it already exists. If there is an error in creating the link, the transaction is rolled back // SafeLink overrides newname if it already exists. If there is an error in creating the link, the transaction is rolled back
func SafeLink(oldname, newname string) error { func SafeLink(oldname, newname string, hard bool) error {
var backupName string var backupName string
// check if newname exists // check if newname exists
if fi, err := os.Stat(newname); err == nil && fi != nil { if fi, err := os.Stat(newname); err == nil && fi != nil {
@ -150,16 +158,34 @@ func SafeLink(oldname, newname string) error {
return err return err
} }
} }
// hardlink oldname to newname if hard {
if err := os.Link(oldname, newname); err != nil { // hardlink oldname to newname
// if that failed, and there is a backupName if err := os.Link(oldname, newname); err != nil {
if len(backupName) > 0 { // if that failed, and there is a backupName
// then move back the backup if len(backupName) > 0 {
if err = os.Rename(backupName, newname); err != nil { // then move back the backup
return err if err = os.Rename(backupName, newname); err != nil {
return err
}
} }
return err
}
} else {
// symlink
relpath, err := filepath.Rel(filepath.Dir(newname), oldname)
if err != nil {
return err
}
if err := os.Symlink(relpath, newname); err != nil {
// if that failed, and there is a backupName
if len(backupName) > 0 {
// then move back the backup
if err = os.Rename(backupName, newname); err != nil {
return err
}
}
return err
} }
return err
} }
// remove the backupName // remove the backupName
if len(backupName) > 0 { if len(backupName) > 0 {