Let’s say I have multiple files I want to delete, and they’re stored one per line in a files.txt file. I can delete them with
set deleteThis to paragraphs of (read "files.txt")
repeat with lineFromFile in deleteThis
set fileName to POSIX file lineFromFile
tell application "Finder" to delete file fileName
end repeat
This is the logic you usually find online — deleting them one by one, but not only does this screw your “Put Back” option (you have to ⌘z multiple times), it also plays the trash sound a bunch of times in a row.
Is there a way to delete multiple files at once, say via storing them in an array and deleting that?
Edit
The answer by #adayzdone is the best so far, but it fails on directories
Try:
set deleteThis to paragraphs of (read "files.txt" as «class utf8»)
set deleteList to {}
tell application "Finder"
repeat with aPath in deleteThis
try
set end of deleteList to (file aPath)
on error
try
set end of deleteList to (folder aPath)
end try
end try
end repeat
delete deleteList
end tell
Yes, Finder will take a list of paths as an argument to the delete command.
set deleteThis to paragraphs of (read "files.txt")
repeat with i from 1 to (count deleteThis)
set item i of deleteThis to POSIX file (item i of deleteThis)
end repeat
tell application "Finder"
delete deleteThis
end tell
Alternatively, if you're able to store the file paths as HFS paths instead of POSIX paths, you can skip the coercion:
set deleteThis to paragraphs of (read "files.txt")
tell application "Finder"
delete deleteThis
end tell
tell application "Finder"
set file_list to entire contents of (choose folder with prompt "Please select directory.")
move file_list to trash
end tell
Related
I have a script that was generously created by another user here, but I've found that it doesn't read recursively through directories. The goal of the script is to read through all sub directories of a directory selected in the Finder, and to write out any absolute paths of files that are 255 characters or longer (path not filename). This is to find files with absolute path lengths that are too long on OSX for a Windows machine with the 255 character path limit, before transferring them from one to the other.
I've tried referencing this post to make it recursive but to no avail as the approach here appears quite different: AppleScript Processing Files in Folders recursively
on run
set longPaths to {}
tell application "Finder" to set theSel to selection
repeat with aFile in theSel
set aFile to aFile as string
set pathLength to count of characters in aFile
if pathLength > 255 then
set end of longPaths to aFile
end if
end repeat
if longPaths is not equal to {} then
-- do something with your list of long paths, write them to a text file or whatever you want
set pathToYourTextFile to (path to desktop folder as string)&"SampleTextFile.txt"
set tFile to open for access file (pathToYourTextFile as string) with write permission
repeat with filePath in longPaths
write (filePath & return as string) to tFile starting at eof
end repeat
close access tFile
end if
end run
Does anyone know the best way to add a recursive element to this script so that theSel includes all files in the subdirectories of the selected directory?
Here's a script which read recursively through directories:
property theOpenFile : missing value
tell application "Finder" to set theSel to selection
if theSel is not {} then
set pathToYourTextFile to (path to desktop folder as string) & "SampleTextFile2.txt"
set theOpenFile to open for access file (pathToYourTextFile as string) with write permission
repeat with aItem in theSel
tell application "Finder" to class of aItem is folder
if the result then my getFilesIn(aItem) -- aItem is a folder
end repeat
close access theOpenFile
end if
on getFilesIn(thisFolder)
tell application "Finder" to set theseFiles to files of thisFolder as alias list
repeat with thisFile in theseFiles
set f to thisFile as string
set pathLength to length of f
if pathLength > 255 then my writeToFile(f)
end repeat
tell application "Finder" to set theseSubFolders to folders of thisFolder
repeat with tSubF in theseSubFolders
my getFilesIn(tSubF) -- call this handler (recursively through this folder)
end repeat
end getFilesIn
on writeToFile(t)
write (t & return) to theOpenFile starting at eof
end writeToFile
Try:
tell application "Finder" to set theSel to every file in (get entire contents of selection)
Or something like that. Sorry, I am without a Mac to test the precise code. Whenever you ask for entire contents, you get everything in all subfolders of your chosen folder.
I've got 2 folders
the first folder contains all the files which I'd like to move to a subfolder of the second folder. I'd like to this based on the first 7 characters of both the file & folder names.
So if the first 7 characters of the subfolder in FOLDER 2 matches the first 7 characters of the file in FOLDER 1. The file get's moved into the subfolder of FOLDER 2
Right now I've got an Applescript which works, but it's terribly slow.
Here's the script so far:
set mgFileList to ""
set mgDestFolder to ""
set mgFilesFolder to (choose folder with prompt "Where are the files stored which you would like to move to the destination?")
set mgDestFolder to (choose folder with prompt "Where is the destination folder?")
set folderList to contents of mgDestFolder
tell application "Finder" to set fileList to files of mgFilesFolder
repeat with aFile in fileList
set prefix to getPrefix(name of aFile)
tell application "Finder"
try
set destinationFolder to (1st folder of mgDestFolder whose name begins with prefix)
move aFile to destinationFolder
end try
end tell
end repeat
on getPrefix(aName)
set prefix to text 1 thru 7 of aName
return prefix
end getPrefix
I've only recently got into Applescripting. Can this be done more efficiently within Applescript? I've searched around for a solution which works with a shell script (which I think will probably be a lot faster), but haven't been able to get any of them working.
I'm working on OSX Mountain Lion 10.8.4
--
edit
I see that I've uploaded the wrong version of the script I've managed to put together so far. Above is the script that is working, but it's really slow. Probably because it doesn't use any shell script.
---------------update-------------------
Here is the final script that is working pretty fast right now:
set mgFilesFolder to choose folder with prompt "Where are the files stored which you would like to move to the destination?"
set mgDestFolder to choose folder with prompt "Where is the destination folder?"
tell application "System Events"
set fileList to files of mgFilesFolder whose name does not start with "."
repeat with aFile in fileList
set prefix to my getPrefix(name of aFile)
try
set destinationFolder to (1st folder of mgDestFolder whose name begins with prefix)
move aFile to POSIX path of destinationFolder
end try
end repeat
end tell
on getPrefix(aName)
try
set prefix to text 1 thru 7 of aName
return prefix
on error
return aName
end try
end getPrefix
The Finder is generally a slow program because it does a lot of things on your computer. Therefore you should avoid using it if possible. In your case these tasks can be done using System Events. Try this, maybe it will be faster. Note that you had a couple mistakes in your code which are fixed in this code.
set mgFilesFolder to choose folder with prompt "Where are the files stored which you would like to move to the destination?"
set mgDestFolder to choose folder with prompt "Where is the destination folder?"
tell application "System Events"
set fileList to files of mgFilesFolder whose name does not start with "."
repeat with aFile in fileList
set prefix to my getPrefix(name of aFile)
try
set destinationFolder to (1st folder of mgDestFolder whose name begins with prefix)
move aFile to POSIX path of destinationFolder
end try
end repeat
end tell
on getPrefix(aName)
try
set prefix to text 1 thru 7 of aName
return prefix
on error
return aName
end try
end getPrefix
Not sure how many files you're working with, but I tested this with 10 folders and ~100 files, and it took less than 4 seconds to run. Working with strings is much faster than working with files, so the script gets the files/folders as strings and builds aliases when they're needed.
set mgFilesFolder to (choose folder with prompt "Where are the files stored which you would like to move to the destination?")
set mgDestFolder to (choose folder with prompt "Where is the destination folder?")
--Always use System Events whenever possible. It's WAY faster than Finder.
tell application "System Events"
set folderList to name of folders of mgDestFolder
set fileList to name of files of mgFilesFolder
end tell
repeat with i from 1 to (count folderList)
set folderName to item i of folderList
set filesToMove to {}
repeat with j from 1 to (count fileList)
set filename to item j of fileList
if filename begins with folderName then
set end of filesToMove to alias ((mgFilesFolder as string) & filename)
end if
end repeat
--Can't use system events for moving files. You have to use Finder.
tell application "Finder"
move filesToMove to alias ((mgDestFolder as string) & folderName & ":")
end tell
end repeat
It might be easier to use shell scripting:
cd FOLDER1; for f in *; do d=../FOLDER2/"${f:0:7}"*; [[ -d $d ]] && mv "$f" "$d"; done
I'm trying to read an html file into a variable in AppleScript, I have the following code.
tell application "Finder"
set theItems to every file of folder folderName
repeat with theFile in theItems
open for access theFile
set fileContents to (read theFile)
end repeat
end tell
Now I get an error like:
Finder got an error: Can’t make document file "index.html" of folder
[...] of startup disk into type «class fsrf».
What am I doing wrong? I followed this example. Are HTML files not recognized as text?
You have to convert the Finder file objects to aliases or text.
read can be used without separate open or close commands. It reads files as MacRoman without as «class utf8» though. (as Unicode text is UTF-16.)
tell application "Finder" to files of folder "HD:Users:lauri:Sites" as alias list
repeat with f in result
read f as «class utf8»
end repeat
Try:
tell application "Finder" to set theItems to every file of folder folderName
repeat with theFile in theItems
set aFile to POSIX path of (theFile as text)
set fileContents to do shell script "cat " & quoted form of aFile
end repeat
Starting from your original code, this should do it:
set folderPath to choose folder
set someData to ""
tell application "Finder"
set theItems to every file of folder folderPath as list
repeat with theFile in theItems
set theFilePath to theFile as text
if characters -5 thru -1 of theFilePath as string is ".html" then
set theFileHandle to (open for access file theFilePath)
set fileContents to (read theFileHandle)
-- for testing, call some function
set someData to someData & return & processHtml(fileContents) of me
close access theFileHandle
end if
end repeat
-- do something with someData here
return someData
end tell
on processHtml(theData)
-- do something with theData here
return theData
end processHtml
As Lauri wrote, you can add "as «class utf8»" to read the file as UTF8. You could also use "as Unicode text" for UTF16. Personally, I like this, because it is vanilla AppleScript and doesn't need shell scripting.
Using open for access is really doing it the hard way.
If you want to read an HTML file with AppleScript, then the best way to do that is to use AppleScript to tell an HTML editor to read the HTML file for you. That is the fundamental way that AppleScript works. That’s why “tell” is the most important command. That’s why you can accomplish your goal of reading an HTML file into a variable in just 3 lines:
tell application "BBEdit"
open (choose file)
set theHTMLSource to the text of document 1
close document 1
end tell
The following script expands on the above to read an arbitrary number of HTML files from a chosen folder. It works with BBEdit 9, and should also work with BBEdit’s free version, which is called “TextWrangler” and is available in Mac App Store. Or you can fairly easily adapt this script for use with HyperEdit or TextEdit or whatever AppleScript-aware HTML/text editor you prefer to use.
tell application "Finder"
set theFolder to (choose folder)
set theFiles to every file of folder theFolder
set theHTMLSourceList to {}
repeat with theFile in theFiles
if the kind of theFile is equal to "HTML document" then
set theName to the name of theFile
tell application "BBEdit"
open file (theFile as text)
set theSource to the text of document 1
copy {theName, theSource} to the end of theHTMLSourceList
close document 1
end tell
end if
end repeat
end tell
When the above script is finished, the variable “theHTMLSourceList” is populated with the names and source code of the entire folder of HTML documents, like so:
{{name of file 1, source of file 1}, {name of file 2, source of file 2}, {name of file 3, source of file 3}}
… and so on up to an arbitrary number of files. But of course you can have the script return the HTML source to you in whatever way you like. The key point is that an AppleScript-aware HTML editor can both read HTML and set AppleScript variables, so you don’t have to write (and debug and maintain) your own HTML reader in tiny AppleScript.
(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
In order to import .MOV files (h.264) to Final Cut Pro I need a correspoding .THM file with the same filename as the .MOV. Is it possible to do this with an AppleScript or Automator? Here is what I want to do:
Create a copy of a "TEMPLATE.THM" file that already exists on my HD
Rename the "TEMPLATE.THM" file using the .MOV filename
Do this to a folder of .MOV files to create a .THM file for every .MOV file both with the same filename.
G'day
This might not be the quickest way — but I see you're still waiting for an answer — so here's something to get you started. Select all your MOV files in the finder and run this in script editor.
set theTemplate to "Macintosh HD:Users:[user name]:[folder:location]:TEMPLATE.THM"
tell application "Finder"
set theFiles to selection
repeat with thisFile in theFiles
set thisName to name of thisFile
set theFolder to container of thisFile
set newFile to duplicate theTemplate to theFolder
set text item delimiters of AppleScript to "."
set thisName to text item 1 of thisName
set text item delimiters of AppleScript to ""
set newName to (thisName & ".THM")
set name of newFile to newName
end repeat
end tell
The easiest way to get the path to the template is to select it in the finder and run this :
tell application "Finder"
set theFile to selection as string
end tell
That will put the path in your results window — just copy it into the first line of the script above.
Hope that helps
m.