Michael Bruny-Groth
Michael Bruny-Groth

Reputation: 3

How to delete empty folders with Applescript?

I'm writing an Applescript which prompts the user to select a folder that it will then run the script on. The script runs and basically sorts files into folders. At the end of the script, I want the empty folders to be deleted.

The script works wonderfully until I want to delete the empty folders at the end.

This is what picks the folder:

tell application "Finder"
    set packageFolder to (choose folder with prompt "Please choose your 
    logo package folder") as string
end tell

And this is the code to delete the empty folders:

tell application "Finder"
    repeat with oneFolder in (get folders of packageFolder)
        if (count items) of oneFolder is 0 then delete oneFolder
    end repeat
end tell

I get the following error:

Result:

error “Can’t get every folder of |”Macintosh HD:Users:michael: Desktop:Logo Package Script Test:\”.” number -1728 from every class cfol» of “Macintosh HD:Users:michael: Desktop: Logo Package Script Test:”

What am I doing wrong here?

Upvotes: 0

Views: 2132

Answers (3)

RobC
RobC

Reputation: 25042

What about hidden files and folders?

The answers provided here and here in this thread, consider any folder which contains only hidden1 files and/or hidden folders to be empty too - resulting in them being deleted, which may lead to the loss of important data.


A Safer Solution:

Using the following solution an empty folder is considered to be empty, only if it does not contain a file(s) and/or non-empty folder(s) - whether they're visible or hidden. However, the exception to this rule is for any folder containing only a hidden .DS_Store file - they will be considered empty, and therefore deleted too.

This solution utilizes the Bash find command and executes it via AppleScripts do shell script command.

tell application "Finder"
  set packageFolder to choose folder with prompt "Please choose your logo package folder"
  set posixPath to quoted form of POSIX path of packageFolder
  do shell script "find " & posixPath & " -name '.DS_Store' -type f -delete && find " & posixPath & " -empty -type d -delete"
end tell

Explanation:

Essentially, this AppleScript executes the following Bash commands:

find /path/to/directory/ -name '.DS_Store' -type f -delete
find /path/to/directory/ -empty -type d -delete

Let's breakdown the parts of those two commands for a better understanding of what's happening:

The first command:

  • find - Search a folder hierarchy for file and folder name(s) which meet a given criteria.

  • path/to/directory/ - This (contrived) path points to the directory where the search should begin from. This will be replaced with a real path, i.e. the path to whichever folder is chosen and assigned to the packageFolder variable via the choose folder command.

    We provide that path (as a POSIX path) to the do shell script command via the part which reads:

    set posixPath to quoted form of POSIX path of packageFolder
    

    The quoted form part ensures the folder path, (i.e. the one assigned to the posixPath variable), is provided to do shell script avoiding further interpretation by the shell - it essentially ensures the path to the chosen folder, whose name may include spaces, is handled correctly.

  • -name - The name of the file to search for, i.e. .DS_Store.

  • -type f - This option specifies that we only want to include a regular file.

  • -delete - This option deletes all files which match the previously specified criteria, i.e. files named .DS_Store.

The second command:

  • find - as per the first command.
  • path/to/directory/ - as per the first command.

  • -empty - This option specifies that we want to include either a regular file or a directory only if it is empty.

  • -type d - This option specifies that we only want to include directories.

  • -delete - as per the first command., however this time we delete empty folders only.


Example Directory (Before and After).

Given a chosen source directory tree like this:

.
├── a
│   ├── .hidden-dir-a
│   │   └── foo.txt
│   └── .hidden-dir-b
├── b
│   └── bb
│       ├── .DS_Store
│       └── bbb
├── c
│   └── .hidden.txt
└── d
    ├── dd
    │   └── ddd
    └── quux.txt

The resultant directory tree (i.e. after running the AppleScript) will be:

.
├── a
│   └── .hidden-dir-a
│       └── foo.txt
├── c
│   └── .hidden.txt
└── d
    └── quux.txt

Refactor:

The current AppleScript (above) assumes that you're using the path which is assigned to the packageFolder variable elsewhere in your script, hence it hasn't been changed. Consequently, it introduces the line which reads;

set posixPath to quoted form of POSIX path of packageFolder    

to obtain a POSIX path equivalent to the chosen folder path.

However, If the packageFolder variable is not used elsewhere, you could refactor the script to the following instead:

tell application "Finder"
  set packageFolder to quoted form of (POSIX path of (choose folder with prompt "Please choose your logo package folder"))
  do shell script "find " & packageFolder & " -name '.DS_Store' -type f -delete && find " & packageFolder & " -empty -type d -delete"
end tell

1 Hidden files and folders on MacOS are those whose name begins with a dot (.). For instance .gitignore


Upvotes: 2

Michael Bruny-Groth
Michael Bruny-Groth

Reputation: 3

This is what ended up working:

on killEmpty(fol)

    tell application "Finder"

        repeat with f in (get fol's folders)

            my killEmpty(f)

        end repeat

        if (count items of fol) is 0 then delete fol

    end tell

    end killEmpty



    tell application "Finder"

    repeat with f in (get folders of folder packageFolder)

        my killEmpty(f)

    end repeat

end tell

I found this solution here: https://discussions.apple.com/message/20188767#message20188767

Thanks again everyone. Sorry about the inaccurately worded question.

Upvotes: 0

wch1zpink
wch1zpink

Reputation: 3142

This works for me on the latest version of macOS High Sierra

set packageFolder to (choose folder with prompt "Please choose your 
    logo package folder") as string

tell application "Finder"
    set theFolders to folders of entire contents of folder packageFolder
    repeat with i from 1 to count of theFolders
        set thisFolder to item i of theFolders
        if (count of items of thisFolder) is equal to 0 then
            delete thisFolder
        end if
    end repeat
end tell

Upvotes: 0

Related Questions