Skip to content

Instantly share code, notes, and snippets.

@PinkShellos
Created April 6, 2022 19:53
Show Gist options
  • Save PinkShellos/9bc08ca8b01a61233833554f8d36a88b to your computer and use it in GitHub Desktop.
Save PinkShellos/9bc08ca8b01a61233833554f8d36a88b to your computer and use it in GitHub Desktop.
"""
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