Scripts to change multiple files and/or folders in a set of nested folders

I recently copied all of the files from an old clip art collection called Art Explosion 750,000 from DVDs to the SSD in my M1 MacBook Air. The files were stored in over 19,000 folders. Folders were nested within other folders several layers deep. Any given folder either contained other folders or contained image files but not both.

I wanted to make two types of changes. First, I wanted convert a set of old eps (encapsulated postscript) files to PDFs to make them compatible with apps that could not handle eps files. Second, I wanted to change the Finder View options for the folders that contained image files but not for the ones that contained only subfolders.

I ended up using Python + AppleScript to accomplish these tasks. The approach used should be applicable to other problems that involve processing many files and/or folders.

Here is the Python program to convert the eps files to PDFs. I found the findall() function online (I have forgotten where). The generation of the PDFs from the eps files is done by the pstopdf command which comes with Ventura in the /usr/bin directory. I put this Python script in a file called eps2pdf.py.


#!/usr/bin/env python3

import fnmatch
import os
import subprocess

# Traverse a nested set of folders looking for files whose names match the
# specified pattern.

def findall(topdir, pattern):
    
    # For each nested folder return the pathname of the folder, a list of
    # the subfolders in the folder, and a list of the files in the folder.
    for path, dirs, files in os.walk(topdir):

        # For the name of each file in the current folder...
        for name in files:

            # If the filename matches the pattern that was passed...
            if fnmatch.fnmatch(name, pattern):
                
                # Return the full pathname of the file.
                yield os.path.join(path, name)

# For each eps file in the nested folders...
# ("." denotes the folder in which this script is run.)
for afile in findall(".", "*.eps"):
    
    try:
        # Generate a PDF from the eps file.
        subprocess.run(["pstopdf", afile], check=True)

        # Delete the eps file.
        try:
            os.remove(afile)
        except:
            print("Failed to remove %s" % afile)
            
    except:
        print("Failed to convert %s to PDF" % afile)

Here is the Python program to set the Finder View options. Because it executes an
AppleScript program for each folder containing image files, it is a bit more complex
than the previous one. It resides in a file called set_view_options.py.


#!/usr/bin/env python3

import os
import subprocess

# Get the full pathname of the directory in which this program is running.
topdir = os.getcwd()

# os.walk() returns the full pathname of the current directory, a list of the
# names of the subdirectories in that directory, and a list of the names of
# the files in that directory.
for path, dirs, files in os.walk(topdir):

    # If this directory contains only files (no subdirectories)...
    if len(dirs) == 0:
    
        script = f'''
        tell application "Finder"
            reopen
	    set target of Finder window 1 to (POSIX file "{path}")
	    set current view of Finder window 1 to icon view
	    set icon size of icon view options of Finder window 1 to 144
	    set arrangement of icon view options of Finder window 1 to arranged by name
	    set shows icon preview of icon view options of Finder window 1 to true
        end tell
        '''
        try:
            print(path)
        except:
            pass

        subprocess.call(['osascript', '-e', script])

# Display the contents of the folder where we started.

script = f'''
tell application "Finder"
    set target of Finder window 1 to (POSIX file "{topdir}")
end tell
'''
subprocess.call(['osascript', '-e', script])

A few notes:

  • python3 does not come preinstalled with Ventura. You will have to install it from here:

    Download Python | Python.org

  • If you are not familiar with running Unix programs using the Terminal app, do this:

    1. Move or copy the script file(s) to the folder at the top of hierarchy you want to process.
    2. Open the Terminal app.
    3. Type "cd " (without the quotation marks but with the space).
    4. Drag the folder at the top of the hierarchy onto the Terminal window. This will add the pathname of the folder after "cd ".
    5. Press the return key.
    6. Type “python3 script_file name” again without the quotation marks.
    7. Press the return key.

Be sure to back up your disk before you run any scripts like these.

These two Python programs show how you can use the os.walk() function to execute
Unix commands and AppleScripts on nested folders and/or files in them. I hope this is useful.

1 Like