AppleScript : How to get files in folder without hidden files? - macos

I actually have two questions.
How to exclude hidden files like .DS_STORE, Icon when I try to get files in folder ?
I've tried "without invisibles" but it seems not working.
How to set my var the_new_folder as an existing folder if already exists ?
Thanks for answers.
My code:
--
-- Get all files in a selected folder
-- For each file, create a folder with the same name and put the file in
--
tell application "Finder"
set the_path to choose folder with prompt "Choose your folder..."
my file_to_folder(the_path)
end tell
on file_to_folder(the_folder)
tell application "Finder"
-- HELP NEEDED HERE
-- HOW TO EXCLUDE HIDDEN FILES (Like Icon, .DS_STORE, etc)
set the_files to files of the_folder
repeat with the_file in the_files
-- Exclude folder in selection
if kind of the_file is not "Folder" then
set the_path to container of the_file
set the_file_ext to name extension of the_file
-- Remove extension of the file name
set the_file_name to name of the_file as string
set the_file_name to text 1 thru ((offset of the_file_ext in (the_file_name)) - 2) of the_file_name
-- Make the new folder with the file name
try
set the_new_folder to make new folder at the_path with properties {name:the_file_name}
on error
-- HELP NEEDED HERE
-- HOW TO SET the_new_folder AS THE EXISTING FOLDER
end try
-- Move the file in the new folder
move the_file to the_new_folder
end if
end repeat
end tell
end file_to_folder
tell application "Finder"
(display dialog ("It's done!") buttons {"Perfect!"})
end tell

Using the System Events context instead of Finder:
bypasses the problem with the AppleShowAllFiles preference[1]
is much faster in general.
Using the visible property of file / folder objects in the System Events context allows you to predictably determine either all items, including hidden ones (by default), or only the visible ones (with whose visible is true):
# Sample input path.
set the_path to POSIX path of (path to home folder)
tell application "System Events"
set allVisibleFiles to files of folder the_path whose visible is true
end tell
Simply omit whose visible is true to include hidden files too.
The code for either referencing a preexisting folder or creating it on demand is essentially the same as in the Finder context:
# Sample input path.
set the_path to POSIX path of (path to home folder)
# Sample subfolder name
set the_subfolder_name to "subfolder"
tell application "System Events"
if folder (the_path & the_subfolder_name) exists then
set subfolder to folder (the_path & the_subfolder_name)
else
set subfolder to make new folder at folder the_path ¬
with properties {name: the_subfolder_name}
end if
end tell
[1] In order to predictably exclude hidden items, a Finder-based solution is not only cumbersome but has massive side effects:
You need to determine the current state of the the AppleShowAllFiles preference (defaults read com.apple.Finder AppleShowAllFiles),
then turn it off.
then kill Finder to make the change take effect (it restarts automatically) - this will be visually disruptive
then, after your code has run, restore it to its previous value.
then kill Finder again so that the restored value takes effect again.

I believe that your first question is not a problem. Your code works fine for me.
As for the second issue, the simplest method is to use the text representation of the_path, and simply build the new folder, and see if it already exists:
set the_path_Text to (the_path as text)
set try_Path to the_path_Text & the_file_name
if (folder try_Path) exists then
set the_new_folder to (folder try_Path)
else
set the_new_folder to make new folder at the_path with properties {name:the_file_name}
end if
If you are truly having difficulty with the first code section, please post a new question with more details, such as a copy of the Result section of the Script.

Thank you to all of you ! #mklement0 #craig-smith
You will find below the corrected code with your help!
If I share this code, you want to be cited for thanks?
--
-- Get all files in a selected folder
-- For each file, create a folder with the same name and put the file in
--
-- Get user folder
set the_path to choose folder with prompt "Choose your folder..."
my file_to_folder(the_path)
on file_to_folder(the_folder)
tell application "System Events"
-- Get all files without hidden
set the_files to files of the_folder whose visible is true
repeat with the_file in the_files
-- Remove extension of the file name
set the_file_ext to name extension of the_file
set the_file_name to name of the_file as string
set the_file_name to text 1 thru ((offset of the_file_ext in (the_file_name)) - 2) of the_file_name
-- Make a new folder or get the existing
set the_path to POSIX path of the_folder
if folder (the_path & the_file_name) exists then
set the_new_folder to folder (the_path & the_file_name)
else
set the_new_folder to make new folder at folder the_path with properties {name:the_file_name}
end if
-- Move the file to the new folder
move the_file to the_new_folder
end repeat
end tell
end file_to_folder
-- Ending dialog
display dialog ("It's done!") buttons {"Perfect!"}

Related

AppleScript - Move all the files contained in subfolder to a top folder

I am looking for an edit to the current script. What I need is moving all the files from subfolders (recursively) in to one top folder, however if a file with the same name exist, create a new top-folder and continue there, this is what I have so far:
tell application "Finder"
try
set Random_name to random number from 100 to 9999
set theTopFolder to (choose folder)
set theFiles to a reference to every file of (entire contents of folder theTopFolder)
set theNewFolder to make new folder at theTopFolder with properties {name:"Flattened Files"}
move theFiles to theNewFolder
on error
set theNewFolder to make new folder at theTopFolder with properties {name:"Flattened Files" & Random_name}
move theFiles to theNewFolder
end try
end tell
Just to be clear the structure of the path is not:
Mainfolder/subfolder/file.xxx but Mainfolder/subfolder/sulbfolder2/subfolder3/....100/file.xxx so the script needs to work recursively which it does but it stops when a file exist with the same name
When a file with the same name exist my edit creates a new folder with Flattened Files+random number however when another file with the same name is moved the script stops for an error instead going ahead and creating a new Flattened Files+randonnumber folder. Any ideas?
Thank you
Your script isn't using recursion, it just lets the Finder get all the files. The additional error you are getting is because you are trying to move the whole list of files again.
One solution would be to step through the file items, testing for duplicates as you go, and make new folders as needed. The following script just moves duplicates to added folders (note that an error will still stop the script). I don't know how you are sorting the file list, so I included a line to uncomment to continue moving file items to the added folder.
set theTopFolder to (choose folder)
tell application "Finder"
set theNewFolder to make new folder at theTopFolder with properties {name:"Flattened Files"}
set theFiles to every file of (entire contents of folder theTopFolder) as alias list
repeat with aFile in theFiles
if file ((theNewFolder as text) & (name of aFile)) exists then -- use added folders for duplicates
set counter to 1
set done to false
repeat until done
set suffix to text -2 thru -1 of ("000000" & counter) -- leading zeros for sorting
set alternateFolder to (theTopFolder as text) & "Flattened Files" & space & suffix
tell me to (do shell script "mkdir -p " & quoted form of POSIX path of alternateFolder) -- make new folder as needed
if file (alternateFolder & ":" & (name of aFile)) exists then -- continue to next one
set counter to counter + 1
else
move aFile to folder alternateFolder
# set theNewFolder to folder alternateFolder -- uncomment to continue moving here after a duplicate
set done to true
end if
end repeat
else
move aFile to folder (theNewFolder as text)
end if
end repeat
end tell

Applescript / Finder select specific items in a folder including those in disclosed subfolders by file name or file path list

Here's our situation:
We have a list of file names and/or full file paths (we can generate either)
The files in our list are all contained under one folder, but scattered across multiple sub-folders. (There are hundreds of items in our select list from thousands of possible files. Selecting manually isn't an option)
We've got the root folder open in list view and all sub-folders, sub-sub etc disclosure-opened (btw thanks to http://hints.macworld.com/article.php?story=20030218164922494 for the shortcut "command, option, control and shift when pressing the right arrow")
With all files visible under one window open we want to automatically select all the items in our file list so that they can then be dragged at once to an application.
I do not believe that with basic AppleScript one can programmatically select multiple items in Finder which span throughout different folders and subfolders within a given folder in one window. Maybe with Cocoa-AppleScript, don't know, however if Avid can open files from file aliases, then the following example AppleScript code is a viable option.
The example AppleScript code makes the following assumptions:
There is a plain text file containing the fully qualified POSIX pathnames of the target files to be processed with Avid and the name of the file is: List of Files to Process with Avid.txt
The name of the folder containing the aliases is: Aliases of Files to Process with Avid
The Desktop is used as the location in the filesystem that the aforementioned file and folder exists, to be processed by Avid.
Obviously these settings can be changed as needed/wanted, see the comments in the code.
Example AppleScript code:
-- # Set the value of the following three property variables:
-- #
-- # The value of 'thisLocation' is an colon-delimited path string, e.g. 'path to desktop as string' returns: "Macintosh HD:Users:me:Desktop:"
-- # NOTE: When not using 'path to (folder)' where 'folder' is a 'folder constant' , the special folder for which to return the path, the value should be in the form of an colon-delimited path string.
-- # See: https://developer.apple.com/library/content/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_cmds.html#//apple_ref/doc/uid/TP40000983-CH216-SW19
-- #
-- # The value of 'theListFilename' is the name of the plain text file containing the fully quilified pathnames of the target files to be opened in Avid.
-- # The value of 'theFolderName' is the name of the temporary folder the temporary aliases will be created in. This folder gets created new each run with new aliases.
-- #
-- # NOTE: For ease of use, as each run is presumed to be temporary to get that job run done, the location of the 'theListFilename' and 'theFolderName' are both in 'thisLocation'.
property thisLocation : (path to desktop as string)
property theListFilename : "List of Files to Process with Avid.txt"
property theFolderName : "Aliases of Files to Process with Avid"
-- # The remaining code is tokenized and should not need to be modified.
tell application "Finder"
if (exists thisLocation & theListFilename) then
tell current application to set theList to read alias (thisLocation & theListFilename)
else
display dialog "The file, \"" & theListFilename & "\", was not found at the expected location." buttons {"OK"} ¬
default button 1 with title "Missing File" with icon 0
return
end if
set theFolderPathname to thisLocation & theFolderName
if not (exists theFolderPathname) then
make new folder at thisLocation with properties {name:theFolderName}
else
move theFolderPathname to trash
make new folder at thisLocation with properties {name:theFolderName}
end if
repeat with i from 1 to length of theList
try
make new alias file at theFolderPathname to POSIX file (paragraph i of theList)
end try
end repeat
reveal theFolderPathname
activate
-- delay 1 -- # In necessary, uncomment and adjust value as appropriate.
select every item of alias theFolderPathname
end tell
In Script Editor, save this script and an application, e.g. Select Files to Process with Avid, and then run as needed after replacing the e.g. List of Files to Process with Avid.txt with the current set of target files to be processed with Avid.
The script does the following:
Checks to see the file e.g. List of Files to Process with Avid.txt exists and if not displays error message and exits.
Checks to see if the folder e.g. Aliases of Files to Process with Avid exist and if not creates it, and if it exists, moves it to the Trash and creates it anew, for the new run of target files to be processed.
Creates an alias of each file listed, as a fully qualified POSIX pathname, in the file e.g.: List of Files to Process with Avid.txt
Opens the folder, e.g. Select Files to Process with Avid, in Finder and selects the aliases.
You are now ready to drag and drop the selected aliases to Avid.
Note: This script assumes the fully qualified POSIX pathnames of the target files to be processes with Avid do not contain linefeeds, carriage returns and or null characters in their pathnames.
This works using the latest version of Sierra.
I was not able to figure out a way to selectively select files in folders with subfolders with subfolders etc. The only solution I was able to come up with was to create folder called “Aliases” and have AppleScript create alias files to all of the ”selected files” and store all of the aliases in the aliases folder. From there you can drag all of the files and drop them into your application as you desired
If you have a plain text file containing POSIX path filenames, each on a separate line like the example in this next image, this version will load the pathnames from the text file directly into the script. Just save this script as an application. You can drag text files directly onto the icon of the app because the code is set up to be a droplet
global theFile
property theInfo : missing value
property theName : missing value
property theList : {}
property theList2 : {}
property aliasFolder : (path to desktop as text) & "Aliases"
on open theFiles
set theInfo to info for theFiles
set theName to POSIX path of theFiles
getLinesofFileAsList(theName)
tell application "Finder"
if not (exists of alias aliasFolder) then
make new folder at (path to desktop as text) with properties {name:"Aliases"}
end if
delete every item of alias aliasFolder
end tell
repeat with i from 1 to count of theList
try
set theResult to POSIX file (item i of theList) as text
set end of theList2 to theResult
tell application "Finder"
set theAliases to make new alias file at aliasFolder to theResult
end tell
end try
end repeat
delay 0.5
tell application "Finder"
activate
delay 0.5
set hmmm to reveal aliasFolder
delay 0.5
set hmmm to select every item of alias aliasFolder
activate hmmm
end tell
end open
on getLinesofFileAsList(theName)
set theFile to theName
set theFile to POSIX path of theName
set theList to read POSIX file theFile as text
set saveTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to linefeed
set theList to paragraphs of theList
if last item of theList is "" then
set theList to reverse of rest of reverse of theList
end if
set AppleScript's text item delimiters to saveTID
end getLinesofFileAsList
--on run
-- -- Handle the case where the script is launched without any dropped files
--end run

Create new folder from files name and move files

(This is a new edit from a previous question of mine which achieved -3 votes. Hope this new one has a better qualification)
I need to create an Automator service to organize a high amount of files into folders. I work with illustrator and from each .ai file I create 3 more formats: [name.pdf], [name BAJA.jpg] and [name.jpg], thats 4 files in total
My problem is that during the week I repeat this process to more than 90 different .ai files. So 90 files * 4 is 360 independent files all into the some project folder.
I want to grab all 4 related files into one folder, and set the folder name as the same as the .ai file.
Since all the file names are identical (except one), I thought of telling the finder to grab all the files with the same name, copy the name, create a folder and put this files inside, but I have a file name variant [name LOW.jpg] Maybe I can tell the script to strip that work as an exception.
That way I will all 4 the files unified into one folder.
Thank you in advance
Update: This problem was originally posted back in 2013, now I have a solution. People help me assembled this script to fit my needs.
I added this as a service and assigned a keyboard shurtcut on MacOs.
This is the code:
on run {input, parameters} -- create folders from file names and move
set output to {} -- this will be a list of the moved files
repeat with anItem in the input -- step through each item in the input
set {theContainer, theName, theExtension} to (getTheNames from anItem)
try
# check for a suffix and strip it off for the folder name
if theName ends with " BAJA" then
set destination to (makeNewFolder for (text 1 thru -6 of theName) at theContainer)
else
set destination to (makeNewFolder for theName at theContainer)
end if
tell application "Finder"
move anItem to destination
set the end of the output to the result as alias -- success
end tell
on error errorMessage -- duplicate name, permissions, etc
log errorMessage
# handle errors if desired - just skip for now
end try
end repeat
return the output -- pass on the results to following actions
end run
to getTheNames from someItem -- get a container, name, and extension from a file item
tell application "System Events" to tell disk item (someItem as text)
set theContainer to the path of the container
set {theName, theExtension} to {name, name extension}
end tell
if theExtension is not "" then
set theName to text 1 thru -((count theExtension) + 2) of theName -- just the name part
set theExtension to "." & theExtension
end if
return {theContainer, theName, theExtension}
end getTheNames
to makeNewFolder for theChild at theParent -- make a new child folder at the parent location if it doesn't already exist
set theParent to theParent as text
if theParent begins with "/" then set theParent to theParent as POSIX file as text
try
return (theParent & theChild) as alias
on error errorMessage -- no folder
log errorMessage
tell application "Finder" to make new folder at theParent with properties {name:theChild}
return the result as alias
end try
end makeNewFolder
Hope this helps.
It's a pity you get downvoted as I, personally, enjoy answering these sorts of questions, as it helps me practise and improve my own skills.
Thanks for posting your solution. I think it's a great gesture and others will find it useful.
This script is a bit shorter than and uses "System Events" instead of "Finder", so will be quicker for large numbers of files:
set IllustratorOutputFolder to "/Users/CK/Desktop/example"
tell application "System Events" to ¬
set ai_files to every file in folder IllustratorOutputFolder ¬
whose name extension is "ai"
set Output to {}
repeat with ai_file in ai_files
set AppleScript's text item delimiters to "."
get name of ai_file
get text items of result
set basename to reverse of rest of reverse of result as text
tell application "System Events"
get (every file in folder IllustratorOutputFolder ¬
whose name begins with basename)
move result to (make new folder ¬
in folder IllustratorOutputFolder ¬
with properties {name:basename})
end tell
set end of Output to result
end repeat
return Output -- list of lists of moved files
Just an alternative way of doing things. Not that it's better or worse, but just a different solution.
You could also save this as script.sh (in TextEdit in plain text mode) and run it with bash script.sh in Terminal:
cd ~/Target\ Folder/
for f in *.ai *.pdf *.jpg; do
dir=${f%.*}
dir=${dir% LOW}
mkdir -p "$dir"
mv "$f" "$dir"
done

Applescript: make new folder structure if it doesn't exist

I've been searching through message boards trying to figure out how to execute this script. Essentially the goal is to be able to run this script while inside a folder and if certain folders do not exist, these folders would then be created. If they do already exist, nothing happens. Here's what I've cobbled together so far:
property archivesFolder : "Archives"
property imagesFolder : "Images"
property proofreadFolder : "Proofreading"
property proofFolder : "Proofs"
property sourceFolder : "Source"
try
tell application "Finder" to set theLocation to (folder of the front window as alias)
end try
tell application "Finder"
if (exists folder archivesFolder) then
(* do nothing *)
else
make new folder at theLocation with properties {name:archivesFolder}
end if
if (exists folder imagesFolder) then
(* do nothing *)
else
make new folder at theLocation with properties {name:imagesFolder}
end if
if (exists folder proofreadFolder) then
(* do nothing *)
else
make new folder at theLocation with properties {name:proofreadFolder}
end if
if (exists folder proofFolder) then
(* do nothing *)
else
make new folder at theLocation with properties {name:proofFolder}
end if
if (exists folder sourceFolder) then
(* do nothing *)
else
make new folder at theLocation with properties {name:sourceFolder}
end if
end tell
What am I doing wrong ? (forgive my n00b code formatting, at work and can't figure out how to create code blocks) Also, is it possible to this not just on the front window, but on a folder that is just selected? Any help given would be awesome.
I suggest two options (to run the script):
Option 1: Take that code (assuming it does what you plan), and save it as an application (with Script Editor).
Then, just drag that application to your window toolbar (you need to have the toolbar visible). To do that, hold the command key while dragging.
Option 2: Use Butler: http://manytricks.com/butler/
(there is a free version, I don't know your OSX version).
It allows you to define system-wide shortcut keys for applescript scripts.
Create a smart item (applescript); paste the code there, and in the name of the script add the shortcut keys: example: create folder here ⇧⌥⌘N
EDIT:
According to your comment, I understand your problem and I can tell you that you were missing the path (the current folder, in your case theLocation)
So, in every case of if (exists folder archivesFolder) then you need to add the of theLocation like this: if not (exists folder archivesFolder of theLocation) then
Finally, knowing that you won't do any thing if the folder exists, just test the false case.
I tested this code and am posting it here:
property archivesFolder : "Archives"
property imagesFolder : "Images"
property proofreadFolder : "Proofreading"
property proofFolder : "Proofs"
property sourceFolder : "Source"
try
tell application "Finder" to set theLocation to (folder of the front window as alias)
end try
tell application "Finder"
if not (exists folder archivesFolder of theLocation) then
make new folder at theLocation with properties {name:archivesFolder}
end if
if not (exists folder imagesFolder of theLocation) then
make new folder at theLocation with properties {name:imagesFolder}
end if
if not (exists folder proofreadFolder of theLocation) then
make new folder at theLocation with properties {name:proofreadFolder}
end if
if not (exists folder proofFolder of theLocation) then
make new folder at theLocation with properties {name:proofFolder}
end if
if not (exists folder sourceFolder of theLocation) then
make new folder at theLocation with properties {name:sourceFolder}
end if
end tell
You can also use a shell script with mkdir, since the option to create intermediate folders won't error if the folder already exists.
# define a list of folders - items will need to be quoted if they contain spaces, etc.
property theFolders : {"Archives", "Images", "ProofReading", "Proofs", "Source"} -- can also nest, e.g. "Inside/One"
try
tell application "Finder" to set targetFolder to (target of the front window) as alias
on error -- no window
set targetFolder to (choose folder)
end try
# build a parameter string from the folder list
set {tempTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, space}
set {theFolders, AppleScript's text item delimiters} to {theFolders as text, tempTID}
do shell script "cd " & quoted form of POSIX path of targetFolder & "; mkdir -p " & theFolders
Try this:
tell application "Finder"
set theLocation to (target of front window) as string
set folderNames to {"archivesFolder", "imagesFolder", "proofreadFolder", "proofFolder", "sourceFolder"}
repeat with theFolder in folderNames
try
make new folder at theLocation with properties {name:"" & theFolder & ""}
end try
end repeat
end tell
This is a script I did to sort a bunch of medical files into subfolders based on the date of service (explaining the "text 5 thru 14" in the script; the files are named according to a pattern so the script can extract the date of service from the filename). Rather than check if the folder already exists, I just put the make folder instruction in a try block; if the folder already exists, the 'try' fails, but the script continues under the assumption that the folder already exists. Using the 'text' item instead of 'character' returns the extracted string as a single string and not as an array of characters that have to be converted back into a string.
tell application "Finder"
set theDirectory to "Internal Disk:Users:steven:Documents:Vondalee:Medical"
set theFiles to every file in folder theDirectory whose name extension is "pdf"
repeat with eachFile in theFiles
set theFileName to the name of eachFile
set theFolder to text 5 thru 14 of theFileName
try
make new folder at theDirectory with properties {name:theFolder}
end try
move eachFile to folder theFolder of folder theDirectory
end repeat
end tell

Automator/Applescript File Sorting and Moving

I was wondering if there was a way in Automator to use Applescript code to get the extension of a file, and if it equals a specific extension (e.g. .pdf or .rtf) move to a specific folder for that extension (e.g if (extension == pdf) { move to folder "~/PDF Files" } else if (extension == rtf) { move to folder "~/Rich Text Files" })
Here's an applescript. Since your request was simple I just wrote it for you. Note how I get the file extension with the subroutine "getNameAndExtension(F)". Normally you can get the file extension from the Finder (called name extension) but I've found that the Finder is not always reliable so I always use that subroutine. That subroutine has always been reliable.
set homeFolder to path to home folder as text
set rtfFolderName to "Rich Text Files"
set pdfFolderName to "PDF Files"
-- choose the files
set theFiles to choose file with prompt "Choose RTF or PDF files to move into your home folder" with multiple selections allowed
-- make sure the folders exist
tell application "Finder"
if not (exists folder (homeFolder & rtfFolderName)) then
make new folder at folder homeFolder with properties {name:rtfFolderName}
end if
if not (exists folder (homeFolder & pdfFolderName)) then
make new folder at folder homeFolder with properties {name:pdfFolderName}
end if
end tell
-- move the files
repeat with aFile in theFiles
set fileExtension to item 2 of getNameAndExtension(aFile)
if fileExtension is "rtf" then
tell application "Finder"
move aFile to folder (homeFolder & rtfFolderName)
end tell
else if fileExtension is "pdf" then
tell application "Finder"
move aFile to folder (homeFolder & pdfFolderName)
end tell
end if
end repeat
(*=============== SUBROUTINES ===============*)
on getNameAndExtension(F)
set F to F as Unicode text
set {name:Nm, name extension:Ex} to info for file F without size
if Ex is missing value then set Ex to ""
if Ex is not "" then
set Nm to text 1 thru ((count Nm) - (count Ex) - 1) of Nm
end if
return {Nm, Ex}
end getNameAndExtension
I'm not at my Apple right now, so I can't play around with Automator and figure it out. But if you could do this by switching finder to list view, sort by type, and then select blocks of files of the same type and drag them into the right folder.

Resources