Created
April 6, 2022 19:53
-
-
Save PinkShellos/9bc08ca8b01a61233833554f8d36a88b to your computer and use it in GitHub Desktop.
This file contains hidden or 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
""" | |
nameshortn.py | |
Resolves issues with filenames that are too long for macOS and causing issues | |
with interacting with them. This is based around the filenames containing | |
metadata as well. This script is designed to look through a file for the base | |
file name that leaves it descriptive but not long. It shortens the filename | |
and then stores the rest as Item Comment metadata (kMDItemComment). | |
Written by Vin Mascoli of FNDTN for ArtClass, 2022 | |
""" | |
import sys | |
import getopt | |
import os | |
import osxmetadata | |
from datetime import datetime | |
import shutil | |
now = datetime.now() | |
date_time = now.strftime("%Y-%m-%d %H:%M:%S") | |
# script arguments - needs to be updated from example | |
def main(argv): | |
try: | |
opts, args = getopt.getopt(argv, "hf:d:t", ["file=", | |
"directory=", | |
"testing"]) | |
except getopt.GetoptError: | |
print("No argument specified, running in Testing Mode...\n") | |
testing_mode() | |
for opt, arg in opts: | |
if opt == '-h': | |
print("Nameshortn shortens your filenames and preserves metadata:") | |
print("Usage:") | |
print("nameshortn.py [-f | --file] /path/to/file.ext") | |
print("nameshortn.py [-d | --directory] /directory") | |
print("nameshortn.py [-t | --testing]") | |
sys.exit() | |
elif opt in ("-f", "--file"): | |
input_arg = arg | |
if os.path.isfile(input_arg): | |
rename_and_add_metadata(input_arg) | |
else: | |
print("Specified input is not a file! Please retry.") | |
sys.exit(2) | |
elif opt in ("-d", "--directory"): | |
input_arg = arg | |
if os.path.isdir(input_arg): | |
file_list = get_file_list(input_arg) | |
for file in file_list: | |
rename_and_add_metadata(file) | |
else: | |
print("Specified input is not a directory! Please retry.") | |
sys.exit(2) | |
elif opt in ("-t", "--testing"): | |
testing_mode() | |
# testing mode code | |
def testing_mode(): | |
# sample file for testing the name shortener | |
test_file = ("07 1 Baseball Hitting Ball _01 1005 7-2 " | |
"Baseball Hitting Ball, Home Run, Crowd Cheers _22 1005 7-3 " | |
"Baseball Hitting Ball, Crowd Cheers _14 1005 7-4 Baseball " | |
"Hitting Ball, Crowd Cheers _13 1005 7-5 Baseball Hit Ball, " | |
"Home Run, Crowd Cheers, Organ In B_.aif") | |
print("ALERT!: nameshortn is running in TESTING MODE!\n") | |
print("Generating bad file for from sample name...") | |
with open(test_file, 'w'): | |
pass | |
print("Bad file name generated in current working directory.") | |
print("Please re-run nameshortn.py with command:\n") | |
print("./nameshortn.py [ -f | --file ] </path/to/bad/file>") | |
# function for getting long filename from path | |
def get_long_name(in_path): | |
partitioned_path = in_path.rpartition('/') | |
name_plus_ext = partitioned_path[-1] | |
strip_ext = name_plus_ext.rpartition('.') | |
long_name = strip_ext[0] | |
return long_name | |
# function for preserving file extension | |
def get_file_ext(filename): | |
partitioned_name = filename.rpartition('.') | |
extension = ['.', partitioned_name[-1]] | |
return ''.join(extension) | |
# function for creating shortened name w/o extension | |
def make_short_name(long_name): | |
name_data = long_name.partition(' _') | |
short_name = name_data[0] | |
return short_name | |
# function for preserving metadata | |
def preserve_metadata(in_file): | |
long_name = get_long_name(in_file) | |
name_data = long_name.partition(' _') | |
raw_meta = name_data[-1] | |
return raw_meta | |
# function for cleaning up raw metadata | |
def clean_metadata(in_file): | |
raw_meta = preserve_metadata(in_file) | |
underscore_to_comma = raw_meta.replace("_", ",") | |
remove_hyphens = underscore_to_comma.replace("-", "") | |
remove_numbers = remove_hyphens | |
numbers = "0123456789" | |
for n in numbers: | |
remove_numbers = remove_numbers.replace(n, "") | |
raw_comments = remove_numbers.split(',') | |
scrubbed_comments = [] | |
for r in raw_comments: | |
if r != '': | |
scrubbed_comments.append(r.strip()) | |
clean_metadata = ", ".join(list(dict.fromkeys(scrubbed_comments))) | |
return clean_metadata | |
# name data processing function | |
def process_name_data(in_file): | |
# file_path = get_path(in_file) | |
short_name = make_short_name(in_file) | |
file_ext = get_file_ext(in_file) | |
new_file_format = [short_name, file_ext] | |
return ''.join(new_file_format) | |
# gather list of all files from specified directory and subdirectories | |
def get_file_list(dir_name): | |
dir_list = os.listdir(dir_name) | |
all_files = [] | |
for entry in dir_list: | |
full_path = os.path.join(dir_name, entry) | |
if os.path.isdir(full_path): | |
all_files = all_files + get_file_list(full_path) | |
else: | |
all_files.append(full_path) | |
return all_files | |
def delete_big_file(in_file): | |
dir_path = in_file.rpartition('/') | |
path_str = '"{}"'.format(dir_path[0]) | |
file_inum = str(os.stat(in_file).st_ino) | |
cmd_lst = ("find", path_str, "-inum", file_inum, "-exec rm -rf {} \\;") | |
sys_cmd = " ".join(cmd_lst) | |
print("Running command:", sys_cmd) | |
os.system(sys_cmd) | |
# def rename_big_file(in_file, new_name): | |
# dir_path = in_file.rpartition('/') | |
# file_inum = str(os.stat(in_file).st_ino) | |
# cmd_lst = ("find", dir_path[0], "-inum", file_inum, "-exec mv {}", new_name, "\\;") | |
# sys_cmd = " ".join(cmd_lst) | |
# print("Running command:", sys_cmd) | |
# os.system(sys_cmd) | |
def rename_and_add_metadata(in_file): | |
print(date_time, ": Input file name: ", in_file) | |
name_out = process_name_data(in_file) | |
meta_out = clean_metadata(in_file) | |
shutil.copy2(in_file, name_out) | |
delete_big_file(in_file) | |
# rename_big_file(in_file, name_out) | |
print(date_time, ": Input file renamed to: ", name_out) | |
meta = osxmetadata.OSXMetaData(name_out) | |
meta.set_attribute("comment", meta_out) | |
print(date_time, ": ", name_out, " comment metadata set to: ", meta_out) | |
if __name__ == "__main__": | |
main(sys.argv[1:]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment