diff --git a/Duplicate Finder/Readme.md b/Duplicate Finder/Readme.md new file mode 100644 index 00000000..122f50f6 --- /dev/null +++ b/Duplicate Finder/Readme.md @@ -0,0 +1,33 @@ +# Duplicate Finder Script + +This script scans a given directory for duplicate files based on their MD5 hash. It provides options to delete or move the duplicate files to another directory. + +## Features + +- Scan a directory recursively for duplicate files. +- Filter files by minimum size. +- Display a list of duplicate files. +- Option to delete or move the duplicate files. + +## Usage + +1. Run the script. +2. Enter the directory you want to scan for duplicates. +3. Specify the minimum file size to consider (in bytes). By default, it's set to 0, which means all files will be considered. +4. The script will display a list of duplicate files, if any. +5. Choose an action: + - `(D)elete`: Deletes all but one of each set of duplicate files. + - `(M)ove`: Moves all but one of each set of duplicate files to another directory. + - `(N)o action`: Exits the script without making any changes. + +## Notes + +- When choosing the delete option, the script keeps the first file it encounters and deletes the rest of the duplicates. +- When choosing the move option, the script keeps the first file it encounters and moves the rest to the specified directory. If the target directory doesn't exist, it will be created. +- The script uses MD5 hashing to identify duplicates. While MD5 is fast, it's not the most secure hashing algorithm. There's a very low probability of hash collisions (different files having the same hash), but it's something to be aware of. + + +## Disclaimer + +Always backup your data before using scripts that modify files. The author is not responsible for any data loss. + diff --git a/Duplicate Finder/duplicate-finder.py b/Duplicate Finder/duplicate-finder.py new file mode 100644 index 00000000..47d7bb7e --- /dev/null +++ b/Duplicate Finder/duplicate-finder.py @@ -0,0 +1,71 @@ +import os +import hashlib + +def get_file_hash(filepath): + """Return the MD5 hash of a file.""" + hasher = hashlib.md5() + with open(filepath, 'rb') as f: + buf = f.read() + hasher.update(buf) + return hasher.hexdigest() + +def find_duplicates(directory, min_size=0): + """Find duplicate files in a directory.""" + hashes = {} + duplicates = {} + + for dirpath, dirnames, filenames in os.walk(directory): + for filename in filenames: + filepath = os.path.join(dirpath, filename) + if os.path.getsize(filepath) >= min_size: + file_hash = get_file_hash(filepath) + if file_hash in hashes: + duplicates.setdefault(file_hash, []).append(filepath) + # Also ensure the original file is in the duplicates list + if hashes[file_hash] not in duplicates[file_hash]: + duplicates[file_hash].append(hashes[file_hash]) + else: + hashes[file_hash] = filepath + + return {k: v for k, v in duplicates.items() if len(v) > 1} + +def main(): + directory = input("Enter the directory to scan for duplicates: ") + min_size = int(input("Enter the minimum file size to consider (in bytes, default is 0): ") or "0") + + duplicates = find_duplicates(directory, min_size) + + if not duplicates: + print("No duplicates found.") + return + + print("\nDuplicates found:") + for _, paths in duplicates.items(): + for path in paths: + print(path) + print("------") + + action = input("\nChoose an action: (D)elete, (M)ove, (N)o action: ").lower() + + if action == "d": + for _, paths in duplicates.items(): + for path in paths[1:]: # Keep the first file, delete the rest + os.remove(path) + print(f"Deleted {path}") + + elif action == "m": + target_dir = input("Enter the directory to move duplicates to: ") + if not os.path.exists(target_dir): + os.makedirs(target_dir) + + for _, paths in duplicates.items(): + for path in paths[1:]: # Keep the first file, move the rest + target_path = os.path.join(target_dir, os.path.basename(path)) + os.rename(path, target_path) + print(f"Moved {path} to {target_path}") + + else: + print("No action taken.") + +if __name__ == "__main__": + main() diff --git a/README.md b/README.md index 74d857ea..6f3c0657 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,8 @@ More information on contributing and the general code of conduct for discussion | Crop Images | [Crop Images](https://github.com/DhanushNehru/Python-Scripts/tree/master/Crop_Images) | A Python script to crop a given image. | | CSV to Excel | [CSV to Excel](https://github.com/DhanushNehru/Python-Scripts/tree/master/CSVToExcel) | A Python script to convert a CSV to an Excel file. | | Currency Script | [Currency Script](https://github.com/DhanushNehru/Python-Scripts/tree/master/currency_script) | A Python script to convert the currency of one country to that of another. | -| Digital Clock | [Digital Clock](https://github.com/DhanushNehru/Python-Scripts/tree/master/Digital%20Clock) | A Python script to preview a digital clock in the terminal. | +| Digital Clock | [Digital Clock](https://github.com/DhanushNehru/Python-Scripts/tree/master/Digital%20Clock) | A Python script to preview a digital clock in the terminal. +| Duplicate Finder | [Duplicate Finder](https://github.com/DhanushNehru/Python-Scripts/tree/master/Duplicate%Fnder) | The script identifies duplicate files by MD5 hash and allows deletion or relocation. | | Display Popup Window | [Display Popup Window](https://github.com/DhanushNehru/Python-Scripts/tree/master/Display%20Popup%20Window) | A Python script to preview a GUI interface to user. | | Face Reaction | [Face Reaction](https://github.com/DhanushNehru/Python-Scripts/tree/master/Face%20Reaction) | A script which attempts to detect facial expressions. | | Fake Profiles | [Fake Profiles](https://github.com/DhanushNehru/Python-Scripts/tree/master/Fake%20Profile) | Create fake profiles. |