Another newbie applescript question. I'm trying to get absolute paths to all of the folders and files inside of a folder upon opening it. I'd like to write something like
on opening folder this_folder
tell application "Finder"
set everyPath to POSIX path of every item in entire contents of this_folder
end tell
repeat with n from 1 to count of everyPath
display dialog item n of everyPath
end repeat
end opening folder
But this s***s a brick so right now I have this even uglier mess.
on opening folder this_folder
tell application "Finder"
set everyName to name of every item in entire contents of this_folder
set everyPath to {}
repeat with n from 1 to count of everyName
set end of everyPath to POSIX path of item n of everyName
end repeat
end tell
repeat with n from 1 to count of everyPath
display dialog item n of everyPath
end repeat
end opening folder
Which diplays dialogs like '/file.ext' when I'm looking for something more like 'User/username/documents/folder/file.ext' and 'User/username/documents/folder/subfolder/file2.ext'.
Judging by my tendency to miss the obvious in the past, I'm assuming there's an easy way to get full path names that I'm just oblivious to, and I would appreciate any help in sorting it out. Thanks!
You can't do it the way you're trying. Normally you can just add the folder path to a name to get the full path. However you're also getting names of files in sub folders, so that won't work because you don't know the subfolder paths. As such getting names from the Finder won't help you. A faster method than the Finder for something like this may be to use the unix program "find".
set this_folder to path to desktop
-- we have to remove the trailing / from the folder path so the
-- returned paths from the find command are correct
set posix_folder to text 1 thru -2 of (POSIX path of this_folder)
-- use find to quickly find the items in this_folder
-- also filter out invisible files and files in invisible folders
-- also filter files inside of package files like ".app" files
set theItems to paragraphs of (do shell script "find " & quoted form of posix_folder & " -name \"*.*\" ! -path \"*/.*\" ! -path \"*.app/*\" ! -path \"*.scptd/*\" ! -path \"*.rtfd/*\" ! -path \"*.xcodeproj/*\"")
And if the find command isn't appropriate then you could use the mdfind command (e.g.. spotlight through the command line) in a similar manner.
Related
I am not a programmer by trade, but an art director on a rather large project where I do many repetitive tasks on a daily basis. One constant is moving files to team member's folders. I want to be able to select some files and have a menu appear for me to choose who will receive the files.
I made some progress but am stuck. The script cannot find the directory I intend the files to go. I fear it has something to do with POSIX paths - or me not defining it as a folder rather than a file? The error reads:
error "File /Volumes/Workbench/Test/CookieMonster wasn’t found." number -43 from "/Volumes/Workbench/Test/CookieMonster"
...even thou there is a folder where it says there isn't. I suspect my syntax is incorrect somehow.
set currentFolder to path to (folder of the front window) as alias
on error -- no open windows
set the currentFolder to path to desktop folder as alias
end try
set artistList to {"CookieMonster", "BigBird", "Bert", "Ernie", "Grouch"}
set assignTo to {choose from list artistList with title "Assign to..." with prompt "Please choose" default items "Bert"}
set assignedArtist to result
set artDeptDir to "/Volumes/Workbench/Test/"
set filePath to {artDeptDir & assignedArtist}
set destinationFolder to filePath as alias
set selected_items to selection
repeat with x in selected_items
move x to folder of filePath
end repeat
If anyone who has insight into my problem, I would love to hear from them. Thank you for taking the time to read this.
The main issue is that the Finder doesn't accept POSIX paths. You have to use HFS paths (colon separated and starting with a disk name).
This version fixes another issue and redundant code was removed
tell application "Finder"
try
set currentFolder to (target of the front window) as alias
on error -- no open windows
set currentFolder to path to desktop
end try
set artistList to {"CookieMonster", "BigBird", "Bert", "Ernie", "Grouch"}
-- no braces {} !
set assignTo to (choose from list artistList with title "Assign to..." with prompt "Please choose" default items "Bert")
if assignTo is false then return
set assignedArtist to item 1 of assignTo
-- no braces {} !
set destinationFolder to "Workbench:Test:" & assignedArtist
move selection to folder destinationFolder
end tell
This is my very first use of AppleScript. I'm trying to use it to move a 100+ folders (and their content files) from one location to another. I'm not just moving the files because I want to maintain the filing system. So I've got the folders listed in a .txt file in this format:
Macintosh HD:Users:Tom:Music:iTunes:Afrika Bambaataa
Macintosh HD:Users:Tom:Music:iTunes:Air
And then I run the following in AppleScript:
tell application "Finder"
set TextFile to (choose file with prompt "Select your text file" of type {"txt"})
set My_Folder to (choose folder with prompt "Select your destination folder")
set List_files to paragraphs of (read TextFile)
move List_files to My_Folder
end tell
However the error I receive is the following:
error "Finder got an error: Handler can’t handle objects of this class." number -10010
Any help on what I'm doing wrong here?
Much appreciated!
tell application "Finder"
set TextFile to (choose file with prompt "Select your text file" of type {"txt"})
set My_Folder to (choose folder with prompt "Select your destination folder")
set List_files to paragraphs of (read TextFile)
move List_files to My_Folder
end tell
Currently, List_files is just a list of text objects, i.e.
{"Macintosh HD:Users:Tom:Music:iTunes:Afrika Bambaataa",
"Macintosh HD:Users:Tom:Music:iTunes:Air", ...}
so what you're asking Finder to do is move some text to a folder, which doesn't make sense. You need to tell Finder that this text represents a path to a folder, by using the folder specifier. Since this can't be done en masse, you have to iterate through the list:
repeat with fp in List_files
move folder fp to My_Folder
end repeat
However, I wouldn't actually do it like this, as that will require 100+ separate move commands - one for each item in List_files. Instead, we'll edit the list items first by prepending the folder specifier to each item, and then move the list of folders altogether in a single command:
repeat with fp in List_files
set fp's contents to folder fp
end repeat
move List_files to My_Folder
Depending how big the files are and how long the transfer will take, the script might time out before the transfer is complete. I'm not honestly sure what impact this would have on an existing file transfer. I suspect that AppleScript will simply lose its connection with Finder, but that the transfer will continue anyway since the command has already been issued (another benefit of using a single move command instead of multiples). But, if you want to avoid finding out, we can extend the timeout duration to be safe:
with timeout of 600 seconds -- ten minutes
move List_files to alias "Macintosh HD:Users:CK:Example:"
end timeout
The final script looks something like this:
tell application "Finder"
set TextFile to (choose file with prompt "Select your text file" of type {"txt"})
set My_Folder to (choose folder with prompt "Select your destination folder")
set List_files to paragraphs of (read TextFile as «class utf8»)
if the last item of the List_files = "" then set ¬
List_files to items 1 thru -2 of List_files
repeat with fp in List_files
set fp's contents to folder fp
end repeat
move List_files to My_Folder
end tell
The extra line that starts if the last item of... is just a safety precaution in case the last line of the text file is a blank line, which is often the case. This checks to see if List_files contains an empty string as its last item, and, if so, removes it; leaving it in would throw an error later in the script.
EDIT: Dealing with folders that don't exist
If the repeat loop throws an error due to an unrecognised folder name, then we can exclude that particular folder from the list. However, it's easier if we create a new list that contains only the folders that have been verified (i.e. the ones that didn't throw an error):
set verified_folders to {}
repeat with fp in List_files
try
set end of verified_folders to folder fp
end try
end repeat
move the verified_folders to My_folder
This also means we can delete the line beginning if the last item of..., as the check that this performs is now going to be caught be the try...end try error-catching block instead.
I'm fairly new at this and while having managed to created several basic scripts over the last few weeks I cannot seem to wrap my head around this one:
Choose Folder (with say 1000 Files)
Enter the number of Files per Folder (say 100)
The script then creates 10 Folders (1000 Files / 100 in each folder)
The script then moves the first 100 files sequentially into the the first folder - repeats till done.
The scripts I've put together for this process to this point are dismal, sloppy and outright pathetic so I dare not share them here.
My experiments have also resulted in the item listing causing issues with moving the files sequentially.
instead of:
ValOne_1.wav
ValOne_2.wav
ValOne_3.wav
ValOne_4.wav
ValOne_5.wav
I get:
ValOne_1.wav
ValOne_10.wav
ValOne_100.wav
ValOne_101.wav
ValOne_102.wav
Thanks
The Finder has a "sort" command so you can use that to avoid the numbering problem you mention. It seems to sort them the way you expect. So using that your workflow becomes easy with a little clever coding. Try the following. You only need to adjust the first 2 variables in the script to suit your needs and the rest of the script should just work.
set filesPerFolder to 3
set newFolderBaseName to "StorageFolder_"
set chosenFolder to (choose folder) as text
tell application "Finder"
-- get the files from the chosen folder and sort them properly
set theFiles to files of folder chosenFolder
set sortedFilesList to sort theFiles by name
set theCounter to 1
repeat
-- calculate the list of files to move
-- also remove those files from the sortedFilesList
if (count of sortedFilesList) is greater than filesPerFolder then
set moveList to items 1 thru filesPerFolder of sortedFilesList
set sortedFilesList to items (filesPerFolder + 1) thru end of sortedFilesList
else
set moveList to sortedFilesList
set sortedFilesList to {}
end if
-- calculate the new folder information and make it
set newFolderName to newFolderBaseName & theCounter as text
set newFolderPath to chosenFolder & newFolderName
if not (exists folder newFolderPath) then
make new folder at folder chosenFolder with properties {name:newFolderName}
end if
-- move the moveList files
move moveList to folder newFolderPath
if sortedFilesList is {} then exit repeat
set theCounter to theCounter + 1
end repeat
end tell
I've been searching a lot for a script like this but I can't find it. I suspect it's similar to this
but not exactly, and I'm not sure how to modify it to work for me.
I have a group of files with multiple names like this....
File Name Vyear #01 (year).ext
FileName Vyear #01 (year).ext
and so forth, the convention is always the same.
Filename (sometimes multiple words) followed by V for Version then the year in parenthesis then followed by a number then another year in parenthesis. It's complicated but it's all there for a reason. What I'm looking for is a way to automate moving all those files into subfolders based on only the first part of that name. So that a file like this...
The Mist V2000 #01 (2011).zip
Would get moved to a folder named this.
The Mist V2000
I'm constantly having to make files like this and I'd love to get them sorted into sub-folders. My problem is that I'm not sure how to select just the first of the name (an account for files that have two or three words in the title) and the volume number only to create the subfolder and then match the filenames for the move.
I hope I'm explaining this properly. If anyone could help I would appreciate it.
Cheers.
Try this. Basically we can calculate the folder name if we know where the "#" character is in the file name. Then we can get all of the text up to there - 2 characters. Then you just have to make that folder and move the file into it. Simple. Good luck.
set sourceFolder to choose folder
tell application "Finder"
set theFiles to files of sourceFolder
repeat with aFile in theFiles
set fileName to name of aFile
if fileName contains "#" then
set poundOffset to offset of "#" in fileName
set folderName to text 1 thru (poundOffset - 2) of fileName
set newFolder to (sourceFolder as text) & folderName & ":"
if not (exists folder newFolder) then
make new folder at sourceFolder with properties {name:folderName}
end if
move aFile to folder newFolder
end if
end repeat
end tell
(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