applescript to move files in numeric order - automation

i started a project for a friend, that involved moving large quantities of files into specific folders. i was using automator as I'm handling the project on my mac, however automator does not have a feature to move section of files that are numbered numerically. for instance i will have files that are say "this file 100" and ill have 100 files like that. and then files that say "That file 50" and ill have 200 files like that. the project is splitting these files into there own folder but in section. so ill need "This file" 1-25 in one folder 26-80 in anther and so on. same is true for the "THAT FILES" but there isn't a pattern just the requirement my friend has asked for.
is there a easy way to write a script that could grab 1-25 or any sequel ordering with the same file name? because moving each file one at a time with automator has been taking to long.
thank you so much in advanced

I am not sure tu fully understand your naming convention, but overall , yes, with Applescript, you can move files into folders based on names, eventually adding sequence numbers.
Because I am not sure about your requirements, at least, here are some sample of syntax for main operations :
Get list of files with names containing xxx in folder myFolder :
Tell Application "Finder" to set myList to every file of myFolder whose name contains "xxx"
Then you have to do a repeat / end repeat loop :
Repeat with aFile in myList
-- do something here with aFile : example with name of aFile
end repeat
In that loop you can extract name, parse it, add a counter,...
To move file to new folder, you must use "move" instruction in a tell "Finder" bloc. Instruction "make" can also be used to create new destination folder based on name or root names of files. You must remember that Applescript commands will give error if same file name already exists in destination folder : Finder is able to add "copy" in the name, but you must do it yourself in Applescript.
Last advice if about the number of files to handle. If that number is not so high (less than few hundreds) Applescript is still OK for speed. If your number of files is much higher, then you must use either shell command or, better, a mix of AS and shell commands. The shell commands can be called from AS with a "do shell script". For instance, getting the list of 1000 files from a folder is time consuming with AS, but much quicker with 'ls' command ! Same for a copy. here is an example of copy using shell 'cp' :
do shell script "cp " & quoted form of (POSIX path of (aFile as string)) & " " & quoted form of (POSIX path of DestFolder) & (quoted form of newFileName)
Note : "Posix path" converts the AS file path (Users:myName:Documents:File.txt) into shell path (Users/myName/Documents/File.txt)
I hope it helps.

Related

Either correct VB6/DOS/SQL function or suggest better alternative

I am currently reprogramming code made long ago by a less than skilled programmer. Granted the code works, and has for a number of years but it is not very efficient.
The code in question is in VB6 with SQL calls and it checks a particular directory on the drive (in this example we will use c:\files) and if a file exists, it moves the file to the processing directory loads the parameters for that particular file and processes them accordingly.
Currently the code uses the DIR function in VB6 to identify a file in the appropriate directory. The only problem is that if a number of files exist in the directory it is a crap shoot as to if it will grab the 5kb file and process it in 3 seconds or if it will grab the 500,000kb file and not process any others for the next 10 minutes.
I search many message boards to find some way to have it pick the smallest file and found I could build a complicated array to perform something similar to a sort but I decided to try alternate ideas instead to hopefully reduce processing time involved. Using ancient DOS knowledge I created something that should work, but for some reason is not (hence posting here).
I made a batch file that we will call c:\test.bat which contained the following lines:
delete c:\test.txt
dir /OS /B c:\files\*.txt>c:\test.txt
This deletes a prior existence of test.txt the pipes a directory without headers sorted by file size smallest to largest into c:\test.txt.
I then inserted the following code into the pre-existing code at the beginning:
Shell "c:\test.bat", vbHide
filepath = "c:\test.txt"
Open filepath For Input As #1
Input #1, filegrabber
Close #1
When I step through the code I can see that this works correctly, except now later on in the code I get a
Runtime error 91 Object variable or with block variable not set
in regard to assigning a FileSystemObject. Am I correct in guessing that FSO and Shell do not work well together? Also if you can suggest a better alternative to getting the smallest file from a existing directory suggestions are appreciated.
No need for sorting.
Just use Dir() to cruise through the directory. Before the loop set a Smallest Long variable to &H7FFFFFFF then inside the loop test each returned file name using the FileLen() function.
If FileLen() returns a value less than Smallest assign that size to Smallest and assign that file name to SmallestFile a String variable.
Upon loop exit if Smallest = &H7FFFFFFF there were no files, otherwise SmallestFile has your file name.
Seems incredibly simple, what am I missing?
Another approach is to use the FileSystemObject's Files collection. Just iterate the files collection for a given folder and evaluate each File object's Size property. So long as you don't have a million files in a folder or something, performance should be fine.

Retrieve the name of the most recent file in a directory using VB.Net

Let's say I am looking for a file that has a name that starts with GLNO1_
I can have hundreds of files that start with those characters, but I want to retrieve the name of the file that starts with those characters that is the most recently modified.
For example, Lets say I have files GLNo1_1, GLNo1_2, GLNo1_3 etc. up to _1000
and number 556 is the file that was modified the most recent.
In VB.Net, how do I retrieve that file name.
The file extensions are of .csv
You'll have to enumerate the files and pick the last one. That's a job for Linq:
Dim dir = New System.IO.DirectoryInfo("c:\foo\bar")
Dim file = dir.EnumerateFiles("GLNo1_*.csv").
OrderByDescending(Function(f) f.LastWriteTime).
FirstOrDefault()
If file IsNot Nothing Then
Dim path = file.FullName
'' etc..
End If
Never overlook the odds that there will be more than one "last one". If your program hasn't run for a while then more than one file could easily have been added by whatever software generates the *.csv files. You generally need to keep track of the files you've already seen before.

Applpescript: Reading Text file for List of Files

I have been trying to cobble together a script to take a list of files from a text document and have applescript go through the list line by line and then do something with the file. In this case it is changing the label on the file, but we would use it in other instances to move files, etc.
It works with a test file on my desktop the files get marked with the purple Label, but when trying to run it in the folder I actually need to it fails with this error message:
error "Finder got an error: Can’t set 1 to 5." number -10006 from 1
The text files are the same except for the length of their content.
Could this be a an issues with filenames, and if so how do I make the script more tolerant.
Here is the script:
set textFileContents to POSIX path of (choose file)
set dataList to paragraphs of (read textFileContents as «class utf8»)
tell application "System Events"
repeat with thisFileName in dataList
tell application "Finder" to set (label index of files whose name is thisFileName) to 5
end repeat
end tell
Any help would be appreciated, thanks.
1080074 3.tif
1080074 2.tif
1080069_A1.tif
Here is the final code from the solution to this problem and some further work I did.
Thanks to #Mark Setchell & #jackjr300 for all of their patient help.
set justpath to POSIX path of (choose folder with prompt "Select the Folder with Files You Want to Use")
set textFileContents to (choose file with prompt "Select the list of files")
set dataList to paragraphs of (read textFileContents as «class utf8»)
tell application "Finder"
repeat with FileName in dataList
try -- need a try block to ignore error, in case that the file has been moved or deleted
set label index of (justpath & FileName as POSIX file as alias) to 5
end try
end repeat
end tell
You seem to have a spurious tell application "System Events" in there. It works like this:
set FileName to POSIX path of (choose file)
set FileRecords to paragraphs of (read FileName)
repeat with ThisFileName in FileRecords
say ThisFileName
tell application "Finder" to set (label index of files whose name is thisFileName) to 5
end repeat
Note that my test file isn't UTF8.
Update
By the way, if all you want do is set the label colour on some files, it may be easier to do that from the Terminal and not worry with Applescript. Say you start the Terminal, and go to your Desktop like this
cd Desktop
you can then change the labels of all files on your Desktop (and in any subdirectories) whose names contain "Freddy" followed by "Frog" (i.e "fileForFreddyFrog.txt", "file from Freddy the Frog.php")
find . -name "*Freddy*Frog*" -exec xattr -wx com.apple.FinderInfo "0000000000000000000700000000000000000000000000000000000000000000" {} \;
You need to specify the folder because the finder has no current folder, except the Desktop if you don't specify a folder.
set textFileContents to choose file
set dataList to paragraphs of (read textFileContents as «class utf8»)
set theFolder to "/Users/jack/Desktop/xxx/yyy" as POSIX file as alias -- change it to the path of your folder
tell application "Finder"
repeat with thisFileName in dataList
try -- need a try block to ignore error, in case that the file has been moved or deleted
set label index of file thisFileName of theFolder to 5
end try
end repeat
end tell
Change the path in the third line of this script
--
If the text file contains the full path of the file, you can use this script.
set textFileContents to choose file
set dataList to paragraphs of (read textFileContents as «class utf8»)
tell application "Finder"
repeat with thisPath in dataList
try -- need a try block to ignore error, in case that the file has been moved or deleted
set label index of (thisPath as POSIX file as alias) to 5
end try
end repeat
end tell

Embed Applescript in Global Field to (Export Container and Trigger Printing with Acrobat)

I am trying to tie together a filemaker script that will export PDFs to a temporary space and use and apple script to print them.
I was able to cull together info from this and some other boards to create an applescript that will print the PDFs using Acrobat from a folder.
I have already created a script that finds the Related attachments and exports them to the desktop.
What I'm having trouble with is merging the two.
I need to export the PDF to a folder or temporary place and trigger the apple script to initiate the printing...
This great Suggestion was provided by Chuck of chivalrysoftware.com/…...
Calculate the location to export by appending the filename to Get( TemporaryPath ).
Export the container field contents to FileMaker to that path.
Save the path to a global field in FileMaker
Use an embedded AppleScript to access the global field path
Use AppleScript to open the file in Preview and print it
This is my apple script:
set myFolder to (path to desktop folder as text) & "Print:"
set myfiles to list folder myFolder without invisibles
repeat with myfile in myfiles
set mycurrentfile to ((myFolder as string) & (myfile as string)) as string
batchprint(mycurrentfile)
end repeat
on batchprint(mycurrentfile)
tell application "Adobe Acrobat Pro"
activate -- bring up acrobat
open alias mycurrentfile -- acrobat opens that new file
tell application "System Events"
tell process "Acrobat"
click menu item "Print..." of menu 1 of menu bar item "File"¬
of menu bar 1
click button "Print" of window "Print"
tell application "System Events"
tell process "Acrobat"
click menu item "Close" of menu 1 of menu bar item "File"¬
of menu bar 1
end tell
end tell
end tell
end tell
end tell
tell application "Finder" -- to move the printed file out
set x to ((path to desktop folder as text) & "Printed PDFs:")
if alias x exists then
beep
else
make new folder at the desktop with properties {name:"Printed PDFs"}
end if
move alias mycurrentfile to folder "Printed PDFs"
end tell
end batchprint
My Filemaker script is:
Go to Related Record[
Show only related records; From table: 'Attachments";
Using layout: "Attachements Report' (Attachments); New window
]
Enter Find Mode
Constrain Found Set [Restore]
Sort Records [Restore; No dialog]
# After finding the related attachments and constraining them to the specific type
# we rename and export them to the desktop
Go to Record/Request/Page [First]
Loop
Set Variable [$Path; Value:
Get ( DesktopPath ) & Attachments::Record number & "-"
& Attachment Type List 2::Prefix_z & Lien::Lien_ID_z1]
Export Field Contents [Attachments::file_c; $Path]
Go to Record/Request/Page [Next: Exit after last]
End Loop
Close Window [Current Window]
First of all, the FileMaker part. Create a global text field in one of your tables. It looks like the Attachments table would be the best place for it. I'll call it g_applescript_parameter for this.
Now we're going to use your $Path variable, which given the calc you've provided should be something like /Aslan/Users/chuck/Desktop/1234-ABC4321. I'd recommend appending a .pdf to the end of it since you'll be exporting PDF files. This may help later.
Also, I would recommend that you use Get( TemporaryPath ) instead of Get( DesktopPath ). Anything you place in the temporary folder will be automatically deleted when you quit FileMaker, which means you don't have to write anything to clean up the desktop folder later and you don't have to manually trash them either. Let FileMaker do that work for you. :)
Regardless, FileMaker uses a path of the form filemac:/volumeName/directoryName/fileName (see the notes in the Specify output file dialog box for the Export Field Contents script step). So you should also prepend filemac: to the beginning of your path variable.
All told, your $Path should be set to something like this:
"filemac:" & Get( DesktopPath ) & Attachments::Record number & "-" &
Attachment Type List 2::Prefix_z & Lien::Lien_ID_z1 & ".pdf"
So your export path for FileMaker should work better now. But AppleScript requires a different format for the path to the same file. Given the above, AppleScript's version should be something like /Users/chuck/Desktop/1234-ABC4321.pdf. In other words, everything after the drive name. Fortunately FileMaker can get the drive name with the Get( SystemDrive ) function. For me that function returns /Aslan/. So if we take the $Path variable as defined above and remove filemac: and the name of the drive as defined by Get( SystemDrive ) and add an extra slash at the beginning, that would convert our FileMaker path into an AppleScript path:
"/" & Substitute( $Path; "filemac:" & Get( SystemDrive ); "" )
Use Set Variable to create an $ASPath variable and set it to the above.
Now within your loop store the contents of the $ASPath variable within that global text field:
Loop
Set Variable[ $Path; …]
Set Variable[ $ASPath; …]
Set Field[Attachments::g_applescript_parameter; $ASPath)
Export Field Contents[Attachments::file_c; $Path]
Go to Record/Request/Page[Next; Exit after last]
End Loop
Now AppleScript can extract that information. I'm assuming that given an accurate file being passed to the batchprint function, batchprint will work, so keep that, but remove everything before it and use something like this:
set _pdf_path to contents of cell "g_applescript_parameter" of current layout
batchprint(_pdf_path)
on batchprint(mycurrentfile)
...
end batchprint
Add a Perform AppleScript step after the Export Field Contents step and place the above code in it.
Note that the first line of the above AppleScript will only work as written from within FileMaker. If you're testing this outside of FileMaker in, for example, Script Editor, then you'll need to make that first line read
tell applicaiton "FileMaker" to set _pdf_path ...
You don't need to do this within the Perform AppleScript script step because by default commands are sent to the enclosing FileMaker application.

AppleScript path being replaced at compile time (New Keynote scripting trouble)

We've got an applescript that tells keynotes to delete slides based on criteria. The new keynote does not have an applescript dictionary, but leaves the old keynote in a subdirectory. So I'm trying to tell AppleScript to talk with the older app rather than the new one.
If I just
tell application "Clean Install:Applications:iWork '09:Keynote.app"
It works, but it doesn't recognize any of the keynote dictionary terms. (delete a slide). So I need to pull out my old friend "using terms from". The challenge here is that this is a precompile directive, so you have to use a string literal, which I don't have on the end user's machine due to different hard drive names.
Ok, still have a plan here. I will write out a new applescript file with the 'using terms from application "Clean Install:Applications:iWork '09:Keynote.app"' and then execute that file... Genius... except for the fact that when AppleScript compiles this line:
using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
Gets changed to:
using terms from application "Keynote"
Which of course calls the new keynote's dictionary which is empty.
Any thoughts on how to keep applescript from helping me out in this way? (or is there a better plan?)
full code:
using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
--using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
tell application "Clean Install:Applications:iWork '09:Keynote.app"
activate
end tell
end using terms from
many thanks!
I'm flyin' blind here (don't have keynote) ... but have you tried using a pre-defined app string as a variable and raw event codes?
You can use Smile to easily get raw event codes by
making a new script window in Smile;
using the "tell" menu item from the Action menu to make that script window application-specific (no tell
block needed);
write a line of code; select line of code
then use the "Copy translate" menu item (cmd-shift-C)
to copy the raw event codes
pasting that raw event code code into a different window that has your working (normal tell block) script
This is what it looks like when I do this for the Mail app:
set origMail to "MyDrive:Applications:Mail.app"
tell application origMail
delete («class mssg» 1 of «class mbxp» "INBOX" of «class mact» 1)
end tell
( When put in a normal tell block, that line of code would be "delete (message 1 of mailbox "INBOX" of account 1)" )
I haven't tried this but I think it will work... when you compile your code with "using terms from" just place your new version of Keynote in the trash. That should force it to use the old version of Keynote's dictionary and your code should compile. If you then save that code as an "applescript application" then it should work on anybody's computer without need to recompile. NOTE: you may need to restart your computer before this trick would work.
Then you just have the problem of targeting the right application on the user's computer because they too might have both versions. Here's some code to find the path to older versions of Keynote and how you would target that.
set lsregister to "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister"
set appName to "Keynote.app"
set nonapplescriptVersion to "6.0"
-- get the path to all Keynote apps
set appPaths to paragraphs of (do shell script lsregister & " -dump | grep " & quoted form of appName)
-- find the one with a version number less than the nonapplescriptVersion of Keynote
set appPath to missing value
repeat with anApp in appPaths
try
-- extract the path
set AppleScript's text item delimiters to "/"
set tis to text items of anApp
set thisPath to "/" & (items 2 thru end of tis) as text
set AppleScript's text item delimiters to ""
-- check the version
if (version of application thisPath) is less than nonapplescriptVersion then
set appPath to thisPath
exit repeat
end if
end try
end repeat
if appPath is missing value then error "Needed application version not installed."
-- use the older version
using terms from application "Keynote"
tell application appPath
activate
-- do whatever
end tell
end using terms from