aboutsummaryrefslogtreecommitdiff
path: root/dupekill
diff options
context:
space:
mode:
authorzlg <zlg@zlg.space>2018-06-25 22:22:28 -0700
committerzlg <zlg@zlg.space>2018-06-25 22:23:38 -0700
commitc7ce65d2a2a14d734d9eefc54e3a63ca2357f2d9 (patch)
treef6ae6435f18dfeeae85d20dbad0ab69d1f51218f /dupekill
parentdupekill: Skip files that can't be accessed (diff)
downloaddupekill-c7ce65d2a2a14d734d9eefc54e3a63ca2357f2d9.tar.gz
dupekill-c7ce65d2a2a14d734d9eefc54e3a63ca2357f2d9.tar.bz2
dupekill-c7ce65d2a2a14d734d9eefc54e3a63ca2357f2d9.tar.xz
dupekill-c7ce65d2a2a14d734d9eefc54e3a63ca2357f2d9.zip
Reorganize project
Diffstat (limited to '')
-rwxr-xr-xdupekill77
1 files changed, 34 insertions, 43 deletions
diff --git a/dupekill b/dupekill
index 19d9123..e8521ac 100755
--- a/dupekill
+++ b/dupekill
@@ -6,33 +6,14 @@ import stat
from optparse import OptionParser
# dupekill - deletes duplicates of existing data
-# version 1.2
-# written by zlg <zlg@zlg.space>
-# and NF <radicalmori@gmail.com>
-#
-# licensed under the...
-#
-# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
-# Version 2, December 2004
-#
-# Copyright (C) 2004 Sam Hocevar
-# 14 rue de Plaisance, 75014 Paris, France
-# Everyone is permitted to copy and distribute verbatim or modified
-# copies of this license document, and changing it is allowed as long
-# as the name is changed.
-#
-# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
-# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-#
-# 0. You just DO WHAT THE FUCK YOU WANT TO.
-#
-# This program is free software. It comes without any warranty, to
-# the extent permitted by applicable law.
-#
-# You have been warned. >:3
+# Version 1.4 (2012-04-02)
+# Written by zlg <zlg@zlg.space>
+# Original idea and code by NF <radicalmori@gmail.com>
+# License: WTFPL <http://sam.zoy.org/wtfpl>
# This function determines whether or not the file needs to be added
# to the list of files in the data list.
+
def need_to_add(filepath, datalist):
found = 0
if len(datalist) == 0:
@@ -44,7 +25,11 @@ def need_to_add(filepath, datalist):
return found != 1
-def dupekill(dry_run=False, recursive=False, verbose=False, all_files=False, path=os.getcwd()):
+def dupekill(dry_run=False, recursive=False, verbose=False, all_files=False, ignore_links=False, path=os.getcwd()):
+
+ if all_files and verbose:
+ print("Error: All operations (-a) or only important ones (-v), not both.")
+ sys.exit(1)
if not os.path.isdir(path):
print("Error: Unable to fetch directory to work with.")
@@ -76,31 +61,33 @@ def dupekill(dry_run=False, recursive=False, verbose=False, all_files=False, pat
# Check for information. If we can't fetch any, there's likely
# a dead symlink or something else wrong.
try:
- filesize = os.stat(filepath).st_size
+ filesize = os.lstat(filepath).st_size
# This occurs when the data points to something that can't be found or
# resolved.
except IOError:
- if verbose:
+ if verbose or all_files:
print("NOT FOUND:", filepath)
- raise
- break
+ continue
# This occurs mostly with symlinks.
except OSError:
- if verbose:
+ if verbose or all_files:
print("DEAD LINK:", filepath)
- raise
- break
+ continue
+
+ if ignore_links:
+ if os.lstat(filepath).st_mode == 41471:
+ continue
deleted = False # We need this flag to determine state before adding to the list
if not os.access(filepath, os.R_OK):
- if verbose:
+ if verbose or all_files:
print("NOTICE: Cannot read from", filepath)
- break
+ continue
if not os.access(filepath, os.W_OK):
- if verbose:
+ if verbose or all_files:
print("NOTICE: Cannot write to", filepath)
# Funny, processed_files will always equal the index of the file
@@ -138,7 +125,7 @@ def dupekill(dry_run=False, recursive=False, verbose=False, all_files=False, pat
if not dry_run:
os.remove(filepath)
- if verbose:
+ if verbose or all_files:
print("DUPE:", filepath)
break
else:
@@ -161,7 +148,7 @@ def dupekill(dry_run=False, recursive=False, verbose=False, all_files=False, pat
if not dry_run:
os.remove(filepath)
- if verbose:
+ if verbose or all_files:
print("DUPE:", filepath)
break
@@ -182,16 +169,20 @@ def dupekill(dry_run=False, recursive=False, verbose=False, all_files=False, pat
if __name__ == '__main__':
try:
usage = "Usage: %prog [options] {path}"
- parser = OptionParser(usage=usage)
- parser.add_option("-d", "--dry", dest='dry_run', action='store_true', default=False, help="displays a list of files dupekill will delete if you run it again without this flag")
- parser.add_option("-r", "--recursive", dest='recursive', action='store_true', default=False, help="Recurses into all directories below the starting point")
- parser.add_option("-v", "--verbose", dest='verbose', action='store_true', default=False, help="Provide more detailed output")
- parser.add_option("-a", "--all-files", dest='all_files', action='store_true', default=False, help="Show all processed files, not just dupes and errors")
+ description = "Deletes files that have duplicate data in them"
+ epilog = "dupekill likes to munch on files. A lot. By default, symlinks and hardlinks that point to the same file will be deleted. Be careful!"
+ version = "%prog version 1.5 (2012-04-05)"
+ parser = OptionParser(usage=usage, description=description, epilog=epilog, version=version)
+ parser.add_option("-d", "--dry", dest='dry_run', action='store_true', default=False, help="don't delete any files")
+ parser.add_option("-r", "--recursive", dest='recursive', action='store_true', default=False, help="recurse into all directories below the current directory")
+ parser.add_option("-v", "--verbose", dest='verbose', action='store_true', default=False, help="provide more detailed output")
+ parser.add_option("-a", "--all-files", dest='all_files', action='store_true', default=False, help="show all processed files, not just dupes and errors")
+ parser.add_option("-i", "--ignore-links", dest="ignore_links", action='store_true', default=False, help="don't process symlinks")
(options, args) = parser.parse_args()
if args and os.path.isdir(args[0]):
path = os.path.abspath(args[0])
else:
path = os.getcwd()
- dupekill(options.dry_run, options.recursive, options.verbose, options.all_files, path)
+ dupekill(options.dry_run, options.recursive, options.verbose, options.all_files, options.ignore_links, path)
except KeyboardInterrupt:
print("Aborted")
pan>Flesh out filter types and ownership statuszlg3-82/+144 It's time for a refactor to a module; the functionality and interface are clashing. 2018-03-18README.mdown: break line correctlyzlg1-1/+1 2018-03-18add 'playlog' list filterzlg2-2/+9 This filter is used to get an idea of which games you're currently playing through, so you can prioritize games to play when you're bored and detect it when you've beaten a game but haven't marked it as such. 2018-03-13Update helpers a bitzlg1-2/+9 At present, user modification is needed to make these seamless. vgup() may need to be axed in favor of telling the user to make an alias. 2018-03-13Make VGSTASH_DB_LOCATION point to a filezlg2-21/+20 It used to point to a directory, which would then look for .vgstash.db. This behavior was kind of backwards and I don't remember why I did it that way. This change gives users more control over where they put their DB. Be sure to update your environment variable if you have it set! 2016-11-18Remove settings from helpers.shZe Libertine Gamer1-5/+0 Sourcing them in .bash_profile screws up login if they're set. 2016-11-15Correct phrasing in README.Ze Libertine Gamer1-4/+4 2016-11-13DerpZe Libertine Gamer1-0/+1 2016-11-03Improve error handling in shell scriptsZe Libertine Gamer4-3/+23 2016-10-24Correct run_again, add recursionZe Libertine Gamer1-0/+4 Loops and functions -- oh my, what a useful combination. :) 2016-10-21Add quotes to correct behavior for arglistZe Libertine Gamer1-1/+1 2016-10-14updater.sh: add recursion, error handlingZe Libertine Gamer1-43/+101 2016-10-14Correct pipe-handling behaviorZe Libertine Gamer1-1/+9 2016-10-12Clarify a method to move between platformsZe Libertine Gamer1-2/+5 Also correct a typo.