0

I would like to build an Automator application that counts the files in the hostfolder, creates a numbered subfolder named " [hostFolder name] [counter] ", moves at maximum 128 files from hostFolder in sequential order into this new subfolder, and loops until all files in hostFolder are sorted into subfolders (i.e. the last subfolder will have fewer than 128 files in it). Before the workflow runs, the hostfolder will always only contain files, no subfolders.

Here's the desired outcome of my ideal workflow using as an example an arbitrary folder containing an arbitrary number of files, also arbitrarily named. (Note I do not need the workflow to rename any files):

A folder named Beans contains 1027 files, the files Legume 0001 to Legume 1027. My Automator application receives the folder Beans as input. Once the workflow has run, the folder Beans now contains 9 subfolders, named Beans 1, Beans 2, Beans 3, and so on all the way to Beans 9.

The subfolder Beans 1 contains files Legume 0001, Legume 0002, Legume 0003, and so on to Legume 0128. The subfolder Beans 2 contains the files Legume 0129 to Legume 0256. In other words, each subfolder contains 128 of the files named Legume **** in sequential order. The only exception is the final subfolder, Beans 9, which contains only 3 files, the files Legume 1025, Legume 1026, and Legume 1027.

  • 2
    Sorry, but we're not a homework or code-writing service. We're here to help if what you have tried so far has hit a snag... – Tetsujin Aug 19 '16 at 17:11
  • Does the source folder only contain files or subfolders too? That is subfolders other then the ones created as a result of doing so to move the files into them? – user3439894 Aug 19 '16 at 18:45
  • Great question @user3439894. The source folder will never initially contain any subfolders. That is to say, it's always going to be files only. – youngdevon Aug 19 '16 at 18:51
  • @Tetsujin I'm organizing audio files for personal use, no homework involved. I've Googled to no avail though, as a newbie, I don't really know where to begin. If you insist my project requires the employment a professional code writing service, please direct me to an affordable one. Or, as an alternative, direct me to whatever online ghetto is reserved for lazy newbie hobbyists. I don't want to offend anyone. – youngdevon Aug 19 '16 at 18:59
  • Are you building sample maps for virtual instruments - NI/Halion etc? It's not something I've done since the 90s, when layering/zoning was a whole lot smaller domain [& I was using in-house proprietary software], but there must be dedicated software out there that can help build this stuff, if you are. – Tetsujin Aug 19 '16 at 19:32
1

This should do what you've asked for. As coded, the only thing you may need to change in the bash script is filesPerSubDir="128" if you want a different file count per subdirectory within the parent directory that's passed to the Run Shell Script action.

Add a Run Shell Script action to your Automator application/service/workflow and set Shell: /bin/bash and Pass input: as arguments. Remove the default code and then copy and paste the code below into the Automator Run Shell Script action.


#!/bin/bash

filesPerSubDir="128"

for argument in "$@"; do
    if [[ -d $argument ]]; then
        cd "$argument" || exit 1
        dirName="$(basename "$argument")"
        fileCount="$(find . -maxdepth 1 -flags nohidden -type f ! -iname ".*" | awk 'END{print NR}')"
        subDirCount="$(( fileCount / filesPerSubDir + 1 ))"
        for (( i = 1; i < subDirCount+1; i++ )); do
            find . -maxdepth 1 -flags nohidden -type f ! -iname ".*" | head -$filesPerSubDir > .moveList
            if [[ -s  .moveList ]]; then
                mkdir "$dirName $i"
                while IFS= read -r file; do
                    mv "$file" "$dirName $i"
                done < .moveList
            fi
        done
        rm .moveList
    fi
done

The image below shows a testing of the code and the workflow completed successfully as noted by the green circles with the check mark. This is just and example of how to implement the Run Shell Script action, it can be done numerous ways however you just have to pick what method you want to pass the Folders in Finder to it, the rest is done by the script.

Automator window


The image below shows the code with syntactical highlighting and is included as it helps in reading the code (especially when the code isn't commented, sorry don't have time at the moment).

syntactical highlight code


Note: The bash script is not coded to handle an embedded newline in the name of a filesystem object, which IMO doesn't belong there in the first place! Feel free to modify as needed/wanted to suite your needs, adding/modifying code and or additional error checking if/when wanted/needed. Additionally, this is by no means the only way to code the script to handle what you want automated but it's what I threw together to get something posted for you. If you have any questions, just ask.

  • I'm absolutely flabbergasted. Thank you so much. It works perfectly. I've been up all night spinning my wheels trying to work with Hazel and Automator to do this but it looks like I simply need to learn shell scripting. This may seem like a menial task to you, but to me, it's a huge inspiration. I've always thought of myself as more of a liberal arts guy rather than a STEM guy, but, seeing how a basic knowledge of coding can streamline my workflow changed me. I'm going to burn through some tutorials in the morning to make sense of this script as a starting point. Thanks again! I owe you. – youngdevon Aug 20 '16 at 8:41
  • @Devon Delamarter, You're welcome, glad I could help! BTW I just modified the code slightly, so you might want to update it in your Automator action. I added || exit 1 to the cd ... command in case for some reason it fails it can exit at that point. Shouldn't fail as the existence of the directory is tested before hand, but extra error checking never hurts. I also removed the $ from the variables in the shell arithmetic as it really isn't needed in that application, just a habit because it's needed to expand the variables elsewhere. :) Just C&P the whole block of code again. – user3439894 Aug 20 '16 at 9:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .