how to fix 100's of alias' on mac after migration? - macos

I really hope someone can help me out with this. I recently moved from one mac to another and did a clean install. I have several folders with hundreds of alias (how do you say the plural of alias?)...
The original file path is "/Volumes/Media Drive/Ableton/Warped Tracks/", and the new path needs to be "/users/joel/Music/Ableton Projects/Warped Tracks"
I see how to fix them one at a time, but that would take hours. I tried this applescript, but had no luck:
https://apple.stackexchange.com/questions/2656/how-do-i-fix-failed-aliases
Can anyone give me a better applescript or another solution? As I mentioned, I tried this applescript:
tell application "Finder"
set these_items to the selection
end tell
repeat with i from 1 to the count of these_items
set this_item to (item i of these_items) as alias
set this_info to info for this_item
if class of this_item is alias then
tell application "Finder"
set original_file to original item of this_item
set this_alias_file_name to displayed name of this_item
set container_folder to container of this_item
set the_path to the POSIX path of (original_file as alias)
set new_path to my replaceText("/Volumes/Media Drive/Ableton/Warped Tracks/", "/users/joel/Music/Ableton Projects/Warped Tracks", the_path)
move this_item to trash
try
make new alias file at container_folder to (POSIX file new_path) with properties {name:this_alias_file_name}
on error errMsg number errorNumber
if errorNumber is -10000 then -- new original file not found, try relinking to old
try
make new alias file at container_folder to (POSIX file the_path) with properties {name:this_alias_file_name}
on error errMsg number errorNumber
if errorNumber is -10000 then -- old original not found. link's dead Jim
display dialog "The original file for alias " & this_alias_file_name & " was not found."
else
display dialog "An unknown error occurred: " & errorNumber as text
end if
end try
else
display dialog "An unknown error occurred: " & errorNumber as text
end if
end try
end tell
end if
end repeat
on replaceText(find, replace, subject)
set prevTIDs to text item delimiters of AppleScript
set text item delimiters of AppleScript to find
set subject to text items of subject
set text item delimiters of AppleScript to replace
set subject to "" & subject
set text item delimiters of AppleScript to prevTIDs
return subject
end replaceText
Any help would be greatly appreciated.
Edit: I think the problem with the applescript for me is that I have folders further down the path that all are different, and THOSE each contain the individual alias files. IE:
"/users/joel/Music/Ableton Projects/Warped Tracks/Folder A/file.alias",/users/joel/Music/Ableton Projects/Warped Tracks/Folder B/file2.alias", etc, etc

I had same issue years ago (transfer between 2 media centers), and I made this program : it asks for folder were all broken alias are and then try to find again original path to rebuild them.
the thing is that any applescript instruction about alias gives error when link is broken, so you must use Finder info window to read original path without error when the link is already broken:
(this program assumes that original file name is unique)
-- Select main folder
tell application "Finder" to set Mon_Dossier to ((choose folder with prompt "Select top folder:" without invisibles) as alias) as string
-- repair alias in this folder and all subsequent folders (entire contents)
tell application "Finder" to set Mes_Alias to every file of entire contents of folder Mon_Dossier whose class is alias file
-- loop on each alias of the folder
repeat with Mon_Alias in Mes_Alias
-- found the original file path of Mon_Alias
-- try first with standard alias call
set F_Source to ""
try
tell application "Finder" to set F_Source to original item of Mon_Alias
end try
if F_Source is "" then
-- the link to original file is broken, then use on windows info method
set F_Source to Origine_Alias(Mon_Alias)
set F_Original to Decompose(F_Source)
-- no need to look original file as is, becuase the link is broken (path changed ?)
-- then directly search for the same file without extension
set Cible to ((chemin of F_Original) as string) & ((Nom of F_Original) as string)
tell application "Finder"
if exists file Cible then
-- file is found without extension
-- then delete alias and create new alias with same name and in same folder
set A_Nom to name of Mon_Alias
set A_Dossier to folder of Mon_Alias
delete Mon_Alias
set Nouvel_Alias to make alias to Cible at A_Dossier
set name of Nouvel_Alias to A_Nom
else
SLog("Alias=" & (Mon_Alias as string) & " File not found=" & Cible)
end if
end tell
else
-- the alias link is still valid : nothing to do ! go to next alias..
end if
end repeat
-- end main program
-- sub routine to find passe of broken link (original path/file can't be found)
-- the result is a unix path like folder/sub_folder/file
on Origine_Alias(F_Alias)
set R to ""
tell application "Finder" to open information window of file (F_Alias as text)
tell application "System Events" to tell process "Finder" to set R to value of static text 19 of scroll area 1 of front window
tell application "Finder" to close front window
return R
end Origine_Alias
-- sub routine to extract, from unix file path, the path, the file name and its extension: result is sent back in a record
-- Warning : we can't use "Posix file of" becuase the path and the file are non longer valid ! (then Posix gives error)
on Decompose(Local_F)
--search the first "." from right to find extension
set X to length of Local_F
repeat while (character X of Local_F is not ".") and (X > 0)
set X to X - 1
end repeat
if X > 0 then
set L_Ext to text (X + 1) thru (length of Local_F) of Local_F
set Local_F to text 1 thru (X - 1) of Local_F
else
L_Ext = "" -- "." not found, then no extension !
end if
-- search first "/" from the right to extract file name
set X to length of Local_F
repeat while (character X of Local_F is not "/")
set X to X - 1
end repeat
set L_Nom to text (X + 1) thru (length of Local_F) of Local_F
set Local_F to text 1 thru (X) of Local_F
try
set L_Chemin to POSIX file Local_F
end try
return {chemin:L_Chemin, Nom:L_Nom, Ext:L_Ext}
end Decompose
-- sub routine log (text log file on desktop)
on SLog(msg)
set the my_log to ¬
((path to desktop) as text) & "My_logfile.txt"
try
-- open file. create it if not yet exist
open for access file the my_log with write permission
-- add text at end of file
write (msg & return) to file the my_log starting at eof
close access file the my_log
on error
try
close access file the my_log
end try
end try
end SLog

Related

How do I get the properties or the info of a file using AppleScript?

I need to write the properties or at least the info of a file I have only the name of (here: "text2.txt") to a textfile.
I tried various ways but each time I just get the properties of the Desktop folder but not the file.
What am I doing wrong here?
try
tell application "Finder"
set this_folder to path of (folder of the front Finder window) as alias
end tell
on error
-- no open folder windows
set this_folder to path to desktop folder as alias
set is_desktop to true
end try
tell application "System Events"
set file_list to the name of every file of this_folder
end tell
tell application "Finder"
set theFile to path to desktop folder
set myList to {}
repeat with n from 1 to count of file_list
set currentFile to item n of file_list
set the_filePath to this_folder
set the_filename to currentFile
if currentFile contains "text2.txt" then
set {creation date:creaDate, modification date:modDate, name:fName, displayed name:dName, name extension:nExt, description:descript, URL:fPath} to properties of the_filePath
set theText to creaDate & "#" & modDate & "#" & fName & "#" & dName & "#" & nExt & "#" & descript & "#" & fPath
do shell script "echo " & theText & ">> $HOME/Desktop/FileProperties.txt"
end if
end repeat
end tell
I think you mostly have it right already.
Finder windows have a 'target', which is the folder that the window looks at. You can get and set the target normally. Everything below the try statement is unchanged.
try
tell application "Finder" to set this_folder to target of front window as alias
on error
set this_folder to (path to desktop) as alias
set is_desktop to true
end try
As alternatives, the script could use TextEdit or its own 'write' command to create the text document. If you're curious, let me know and I'll add those options.
Okay… here is a script you can try that should handle the writing within applescript. I've made a few other tweaks, all of which are commented (which unfortunately, make the script appear longer than it really is).
Applescript has a built-in 'File Read/Write suite' which you can read about each command in the Language Guide here, but in a nutshell, you use these commands to write to a new file, replace or append text to an existing file.
p.s. I changed some of your variable names
-- Make front window specifier a global var. Unnecessary if you integrate System Events block into Finder block (see below)
global fw
tell application "Finder"
try
set targFol to target of front window as alias
set fw to front window
on error
set targFol to (path to desktop) as alias
set fw to make Finder window to targFol
end try
end tell
The system events block below could also be handled by the Finder. If the folders you're rooting through don't typically have thousands of files in them (or if the alternative line is sufficient), you should consider doing so, as the primary advantage of using System Events is performance with high file counts. I don't think any changes would be required beyond removing the appropriate 'tell/end' statements.
tell application "System Events"
-- Some filtering options as an alternative to the repeat loop
set txFiles1 to files of targFol whose kind is "Plain Text Document"
set txFiles2 to files of targFol whose kind is "Plain Text Document" and name is "text2.txt"
set txFile to item 1 of txFiles2
-- Alternatively, you can just use the file itself, without any of the rigmarole.
set txFile to file "text2.txt" of targFol
end tell
tell application "Finder"
set {creation date:creaDate, modification date:modDate, name:fName, displayed name:dName, name extension:nExt, description:descript, URL:fPath} to properties of targFol
set newText to creaDate & "#" & modDate & "#" & fName & "#" & dName & "#" & nExt & "#" & descript & "#" & fPath as text
end tell
-- Write the properties as text to a text file -- requires the 'class furl' bit to work
set tf to (path to desktop as text) & "FileProperties.txt" as «class furl»
-- Alternatively, you could create the text file in the target folder
-- set tf to (targFol as text) & "FileProperties.txt" as «class furl»
close access (open for access tf)
write newText to tf as text
-- And some obvious things you can do with your new text file
tell application "TextEdit" to open tf
tell application "Finder" to select tf
set rtext to read tf
I made a few adjustments to your code. Maybe something like this will help you out.
property theFile : "text2.txt"
tell application "Finder"
try
-- Gets The Name Of The Front Finder Window If There Is One Opened
set containerName to name of front Finder window as POSIX file as text
-- Checks If The File "text2.txt" Exists In That Folder
-- fileExists Will Be Set To True Or False Depending On The Results
set fileExists to (containerName & theFile) as alias exists
on error errMsg number errNum
-- If Either Of The Previous Commands Throws An Error
-- This Will Give You An Option To Choose A Folder Where You Think
-- The File "text2.txt" Is Located
activate
set containerName to my (choose folder with prompt "Choose A Folder") as text
end try
try
-- Checks If The File "text2.txt" Exists In The New Chosen Folder
set fileExists to (containerName & theFile) as alias exists
on error errMsg number errNum
-- If "text2.txt" Does Not Exist In This Folder Either, Script Stops Here
return
end try
delay 0.1
-- If fileExists Is Set To True From Previous Commands
if fileExists then
set fullFilePath to (containerName & theFile) as alias
set {creation date:creaDate, modification date:modDate, name:fName, displayed name:dName, name extension:nExt, description:descript, URL:fPath} to properties of fullFilePath
set theText to creaDate & "#" & modDate & "#" & fName & "#" & ¬
dName & "#" & nExt & "#" & descript & "#" & fPath
tell current application to (do shell script "echo " & theText & ¬
">> $HOME/Desktop/FileProperties.txt")
end if
end tell

Batch Convert *.numbers to *.csv AppleScript

I was looking for a script that would batch convert all *.numbers files in a given folder to *.csv files.
I found the following on GitHub and added an additional line as suggested in the comments suggestion. When I run the script, Numbers launches and opens the test file from the folder specified - but the file is not exported. Numbers just stays open and terminal errors out with:
/Users/Shared/Untitled.scpt: execution error: Numbers got an error: Invalid key form. (-10002)
The script (located in /Users/Shared) has the following permissions:
-rwxr-xr-x
#!/usr/bin/osascript
on run argv
set theFilePath to POSIX file (item 1 of argv)
set theFolder to theFilePath as alias
tell application "Finder" to set theDocs to theFolder's items
-- Avoid export privilege problem
set privilegeFile to (theFolder as text) & ".permission"
close access (open for access privilegeFile)
repeat with aDoc in theDocs
set docName to aDoc's name as text
if docName ends with ".numbers" then
set exportName to (theFolder as text) & docName
set exportName to exportName's text 1 thru -9
set exportName to (exportName & "csv")
tell application "Numbers"
open aDoc
delay 5 -- may need to adjust this higher
tell front document
export to file exportName as CSV
close
end tell
end tell
end if
end repeat
end run
Any suggestions?
Here is what I did and works for me in macOS High Sierra:
In Terminal:
touch numb2csv; open -e numb2csv; chmod +x numb2csv
• This creates an empty ASCII Text file named numb2csv.
• Opens, by default, numb2csv in TextEdit.
• Makes the numb2csv file executable.
Copy and paste the example AppleScript code, shown further below, into the opened numb2csv file.
Save and close the numb2csv file.
In Terminal executed the numb2csv executable file, e.g.:
./numb2csv "$HOME/Documents"
This created a CSV file of the same name as each Numbers document in my Documents folder, not traversing any nested folders.
Example AppleScript code:
#!/usr/bin/osascript
on run argv
set theFilePath to POSIX file (item 1 of argv)
set theFolder to theFilePath as alias
tell application "System Events" to set theDocs to theFolder's items whose name extension = "numbers"
repeat with aDoc in theDocs
set docName to aDoc's name as text
set exportName to (theFolder as text) & docName
set exportName to exportName's text 1 thru -8
set exportName to (exportName & "csv")
tell application "Numbers"
launch
open aDoc
repeat until exists document 1
delay 3
end repeat
tell front document
export to file exportName as CSV
close
end tell
end tell
end repeat
tell application "Numbers" to quit
end run
NOTE: As coded, this will overwrite an existing CSV file of the same name as each Numbers file processed, if they already exist. Additional coding required if wanting to not overwrite existing files
If you receive the Script Error:
Numbers got an error: The document “name” could not be exported as “name”. You don’t have permission.
It is my experience that the Numbers document was not fully opened prior to being exported and that increasing the value of the delay command resolves this issue. This is of course assuming that one actually has write permissions in the folder the target Numbers documents exists.
Or one can introduce an error handler within the tell front document block which, if my theory is right about the target document not being fully loaded before the export, will give additional time, e.g.:
Change:
tell front document
export to file exportName as CSV
close
end tell
To:
tell front document
try
export to file exportName as CSV
close
on error
delay 3
export to file exportName as CSV
close
end try
end tell
Note: The primary example AppleScript code is just that and does not contain any error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors. See included example directly above.
I was looking for that, unfortunately, that doesn’t work anymore.
This line
tell application "System Events" to set theDocs to theFolder's items whose name extension = "numbers"
Gets the following error:
execution error: Can’t make file "file.numbers" of application "System Events" into the expected type. (-1700)
macOs Big Sur Versio 11.01
automator version 2.10
Numbers version 10.3.5
Inspired by this thread and those articles Exporting Numbers Documents and Get full directory contents with AppleScript
The following code works:
#!/usr/bin/osascript
log "Start"
property exportFileExtension : "csv"
tell application "Finder"
activate
set sourceFolder to choose folder with prompt "Please select directory."
set fileList to name of every file of sourceFolder
end tell
set the defaultDestinationFolder to sourceFolder
repeat with documentName in fileList
log "documentName: " & documentName
set fullPath to (sourceFolder as text) & documentName
log "fullPath: " & fullPath
if documentName ends with ".numbers" then
set documentName to text 1 thru -9 of documentName
tell application "Finder"
set newExportItemName to documentName & "." & exportFileExtension
set incrementIndex to 1
repeat until not (exists document file newExportItemName of defaultDestinationFolder)
set newExportItemName to ¬
documentName & "-" & (incrementIndex as string) & "." & exportFileExtension
set incrementIndex to incrementIndex + 1
end repeat
end tell
set the targetFileHFSPath to ¬
(defaultDestinationFolder as string) & newExportItemName
tell application "Numbers"
launch
open fullPath
with timeout of 1200 seconds
export front document to file targetFileHFSPath as CSV
end timeout
close
end tell
end if
end repeat
user3439894's answer works with a few change:
exists document 1 => number of documents > 0

Combining two (applescript) scripts into one

I'm trying to simplify my workflow by combining the following two applescripts into one, they work fine separately but it'd be more efficient to combine them.
In short, script A trims a file name into the last 3 characters and Script B adds the folder name (where the files reside) to the file name.
This might be a very simple fix but I'm script-writing challenged so any help is welcomed.
SCRIPT A:
on open whichFile
repeat with aFile in whichFile
tell application "Finder"
set filename to name of aFile
set name of aFile to ((characters -1 thru -7 of filename) as string)
--set name of whichFile to ((characters 1 thru -4 of filename) as string) --trim last 3
end tell
end repeat
end open
SCRIPT B
on open theDroppedItems
repeat with a from 1 to length of theDroppedItems
set theCurrentDroppedItem to item a of theDroppedItems
set theCurrentDroppedItem to theCurrentDroppedItem as string
tell application "System Events"
set folderPath to theCurrentDroppedItem as string
--display dialog (folderPath)
set AppleScript's text item delimiters to ":"
set newFileName to (text item -4 of folderPath as string) & "-" & (text item -2 of folderPath as string) & "-" & (text item -1 of folderPath as string)
--display dialog (newFileName)
--rename file
set fileAlias to (theCurrentDroppedItem) as alias
set the name of fileAlias to newFileName
end tell
end repeat
end open
You can start by opening a new Script Editor document for the combined script. The open handler is passed a list of file items, so you can add a new handler declaration with an empty repeat statement that steps through the dropped items. From there, just identify the statements that perform the various operations (trim name, get folder name, etc), and copy them into the new open handler's repeat statement, editing as needed to use consistent variable names.
Once the new script is running, then you can look at optimizing it by combining and/or rearranging statements that may be doing the same thing in the different scripts. It can also be helpful to organize functions into their own handlers, such as the getNamePieces handler below. I also like to add a run handler with a choose file dialog so that you can test without having to drag items onto a droplet.
Note that the file name includes any extension, so you should break it apart in order to work with just the name part. There is also a bit of unnecessary thrashing about in the script that gets the folder name, so after cleaning it up your script could look something like:
on run
open (choose file with multiple selections allowed)
end run
on open droppedItems
repeat with anItem in droppedItems
set {folderPath, theName, extension} to getNamePieces from anItem
set trimmedName to text -1 thru -3 of theName -- work with just the name part
tell application "System Events"
set folderName to name of disk item folderPath
set newName to folderName & "-" & trimmedName & extension -- assemble the pieces
log newName -- for testing
# set name of anItem to newName -- uncomment to go live
end tell
end repeat
end open
to getNamePieces from someItem -- return the containing folder path, the name, and the extension
tell application "System Events" to tell disk item (someItem as text)
set theContainer to path of the container
set {theName, extension} to {name, name extension}
end tell
if extension is not "" then
set theName to text 1 thru -((count extension) + 2) of theName -- just the name part
set extension to "." & extension
end if
return {theContainer, theName, extension}
end getNamePieces

Applescript - Recursively searching through directories

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.

Applescript to get file name without extension

I have an applescript where the user will pick one file and i need to get the name of that file minus the extension.
I found a post on a different site that said this would work:
tell application "Finder"
set short_name to name of selected_file
end tell
But it returns the extensions as well. How can I get just the name of the file?
You can ask the Finder or System Events for the name extension and remove that part from the full name. This will also avoid issues with names that have periods in them or extensions that may not be what you think they are.
set someItem to (choose file)
tell application "System Events" to tell disk item (someItem as text) to set {theName, theExtension} to {name, name extension}
if theExtension is not "" then set theName to text 1 thru -((count theExtension) + 2) of theName -- the name part
log theName & tab & theExtension
This should work with filenames that contain periods and ones that don't have an extension (but not both). It returns the last extension for files that have multiple extensions.
tell application "Finder"
set n to name of file "test.txt" of desktop
set AppleScript's text item delimiters to "."
if number of text items of n > 1 then
set n to text items 1 thru -2 of n as text
end if
n
end tell
name extension also returns the last extension for files with more than one extension:
tell application "Finder"
name extension of file "archive.tar.gz" of desktop -- gz
end tell
Here's the script for getting just the filenames.
set filesFound to {}
set filesFound2 to {}
set nextItem to 1
tell application "Finder"
set myFiles to name of every file of (path to desktop) --change path to whatever path you want
end tell
--loop used for populating list filesFound with all filenames found (name + extension)
repeat with i in myFiles
set end of filesFound to (item nextItem of myFiles)
set nextItem to (nextItem + 1)
end repeat
set nextItem to 1 --reset counter to 1
--loop used for pulling each filename from list filesFound and then strip the extension
--from filename and populate a new list called filesFound2
repeat with i in filesFound
set myFile2 to item nextItem of filesFound
set myFile3 to text 1 thru ((offset of "." in myFile2) - 1) of myFile2
set end of filesFound2 to myFile3
set nextItem to (nextItem + 1)
end repeat
return filesFound2
This script uses ASObjC Runner to parse file paths. Download ASObjC Runner here.
set aFile to choose file
tell application "ASObjC Runner" to set nameS to name stub of (parsed path of (aFile as text))

Resources