I'm trying to write all the song names my iTunes to a txt document. The first issue I had was that I can't seem to correctly loop the operation. Here is my test case with the first 15 songs in my iTunes:
tell application "TextEdit"
make new document
end tell
tell application "iTunes"
set trNameID1 to name of track 1
set trNameID2 to name of track 2
set trNameID3 to name of track 3
set trNameID4 to name of track 4
set trNameID5 to name of track 5
set trNameID6 to name of track 6
set trNameID7 to name of track 7
set trNameID8 to name of track 8
set trNameID9 to name of track 9
set trNameID10 to name of track 10
set trNameID11 to name of track 11
set trNameID12 to name of track 12
set trNameID13 to name of track 13
set trNameID14 to name of track 14
set trNameID15 to name of track 15
tell application "TextEdit"
set text of document 1 to {trNameID1 & "
", trNameID2 & "
", trNameID3 & "
", trNameID4 & "
", trNameID5 & "
", trNameID6 & "
", trNameID7 & "
", trNameID8 & "
", trNameID9 & "
", trNameID10 & "
", trNameID11 & "
", trNameID12 & "
", trNameID13 & "
", trNameID14 & "
", trNameID15} as text
end tell
end tell
When I try to loop it, the txt document only contains the last song name, for instance:
tell application "TextEdit"
make new document
end tell
tell application "iTunes"
set trNum to 1
repeat 15 times
set trNameID to name of track (trNum)
tell application "TextEdit"
set text of document 1 to trNameID & "
"
end tell
end repeat
end tell
This will only output the fifteenth song's name onto the txt document.
I realize that this may be very basic, but I have literally been using applescript for about 48 hours, and I can't seem to figure this out. I would like all of the song names to be in a txt document so I can read and analyze the strings in c++. Does anyone have any ideas?
Also, I'm not sure if there is a way, in AppleScript, to look at the entire iTunes library and see the last song, record that song's id in iTunes, and then make a repeat loop that goes through that id. This way the loop would work for exactly the number of songs that are in the library.
Any ideas would be very much appreciated!
You don't really need a repeat loop at all. You can get track names directly from iTunes. You get it in list format so we just convert that list into a string separating the list items with a return character. Then we write it to TextEdit. So this code optimizes #Michele Percich's code by eliminating the repeat loop and using applescript's text item delimiters to convert the list to a string for use in TextEdit.
tell application "iTunes"
set trackNames to name of every track in (first playlist whose special kind is Music)
end tell
set text item delimiters to return
set trackNames to trackNames as text
set text item delimiters to ""
tell application "TextEdit"
make new document
set text of document 1 to trackNames
end tell
You need to increment the value of trNum variable at the end of your repeat loop:
set trNum to trNum + 1
Or better use a different repeat syntax:
repeat with trNum from 1 to 15
And also to add (and not replace) the track name to the document:
set text of document 1 to text of document 1 & trNameID & return
However, this probably is a better way to do what you want:
tell application "iTunes"
set trackList to ""
set allTracks to every track in (first playlist whose special kind is Music)
repeat with currentTrack in allTracks
set trNameID to name of currentTrack
set trackList to trackList & trNameID & return
end repeat
end tell
tell application "TextEdit"
make new document
set text of document 1 to trackList
end tell
i see you all use the:
tell application "TextEdit"
make new document
set text of document 1 to trackNames
end tell
command
You can use a faster way:
set textlocation to "/users/yourusername/desktop/test.txt"
set Line_1 to "Hello this is line one, if you want more lines just copy > this script and change the variables."
do shell script "echo " & quoted form of Line_1 & " >> " & quoted form of textlocation
You can see in the script the 2 ">>" signs, this will add each textline in a new line in a txt file.
If there is only one ">" the text will replace the other text.
Here is an example:
First with 2 ">>" lines
do shell script "echo Hey this is one line. >> /Users/Yourusername/desktop/Add.txt"
do shell script "echo And this is the second one. >> /Users/Yourusername/desktop/Add.txt"
This script will make a txt file like this:
Hey this is one line.
And this is the second one.
Now with 2 ">" lines
do shell script "echo Hey this is one line > /Users/Zl109819/desktop/Add.txt"
do shell script "echo And this is the second one > /Users/Zl109819/desktop/Add.txt"
This script will make a txt file like this:
And this is the second one.
Related
I'm making a Automator to jump from citation in Word to the reference software(Zotero). But I can't find a AppleScript to extract text of selected field code (the first step).
The field code in Word is
ADDIN ZOTERO_ITEM CSL_CITATION {"citationID":"AFUiwuqi","properties":{"formattedCitation":"[1]","plainCitation":"[1]","noteIndex":0},"citationItems":[{"id":9752,"uris":["http://zotero.org/users/6410528/items/YYTRWPHH"],"itemData":{"id":9752,"type":"article-journal","container-title":"Nature","DOI":"10.1038/s41586-019-1737-7","ISSN":"0028-0836, 1476-4687","issue":"7782","page":"324-329","title":"Controlled flight of a microrobot powered by soft artificial muscles","volume":"575","author":[{"family":"Chen","given":"Yufeng"},{"family":"Zhao","given":"Huichan"},{"family":"Mao","given":"Jie"},{"family":"Chirarattananon","given":"Pakpong"},{"family":"Helbling","given":"E. Farrell"},{"family":"Hyun","given":"Nak-seung Patrick"},{"family":"Clarke","given":"David R."},{"family":"Wood","given":"Robert J."}],"issued":{"date-parts":[["2019",11,14]]}}}],"schema":"https://github.com/citation-style-language/schema/raw/master/csl-citation.json"}
Here is the script process:
Extract text from selected field code in Word (This is the question)
Get the uris text(http://zotero.org/users/6410528/items/YYTRWPHH)
Get the item-codes (YYTRWPHH).
Open url (zotero://select/library/items?itemKey=YYTRWPHH)
Now I use VBA to extract field code text, see below. But in this way, the file will be changed. So I want to do this via AppleScript.
Sub GetFiledsCodes()
Dim myRange As Range, myCodes As String
Set myRange = Selection.Range
With myRange
If .Fields.Count = 0 Then
MsgBox "No Code!", vbInformation
Exit Sub
Else
.Fields.Update
.TextRetrievalMode.IncludeFieldCodes = True
.TextRetrievalMode.IncludeHiddenText = True
myCodes = .Text
myCodes = VBA.Replace(myCodes, Chr(19), "{")
myCodes = VBA.Replace(myCodes, Chr(21), "}")
.SetRange .End, .End
.InsertAfter myCodes
.Font.Name = "Times New Roman"
.Font.Size = 12
.Cut
End If
End With
End Sub
PS:
Here is my process in Automator(it can work but using VBA):
Run AppleScript
on run {input, parameters}
tell application "Microsoft Word" to activate
tell application "Microsoft Word"
run VB macro macro name "GetFiledsCodes"
delay 0.5
end tell
return input
end run
Get contents from clipboard
Extract URLs from Text
Filter Paragraphs begin with http://zotero.org/users/
Copy to Clipboard
Run AppleScript
set myStr to do shell script "pbpaste"
tell application "Zotero" to activate
set AppleScript's text item delimiters to "
"
set myList to every text item of myStr
set zoterocode to ""
set codes to ""
repeat with j from 1 to the length of myList
set itemValue to item j of myList
set zoterocode to (do shell script "sed -E 's#http://zotero.org/users/[0-9]+/items/##g' <<< " & itemValue)
if j = 1 then
set codes to zoterocode
else
set codes to codes & "," & zoterocode
end if
end repeat
tell application "System Events"
key code 18 using {command down, control down, option down}
delay 0.5
set collectionKey to do shell script "pbpaste"
if collectionKey = myStr then
set theurl to "zotero://select/library/items?itemKey=" & codes
else
set theurl to collectionKey & "/items?itemKey=" & codes
end if
open location theurl
end tell
That helps a lot. Okay, so this isn't a turnkey solution for your question but I don't think you really need that as you'd probably end up having to tell me more about how this app works than is really necessary. So this script focuses on your initial question about getting the field codes/result ranges from a merge document.
I put together a simple mail merge consisting of labels and a data file with 8 records, each of which have 5 fields: {"«LastName»", "«JobTitle»", "«Company»", "«City»", "«Web»"}. The latter is the key field.
Basically, the script runs through the data merge document and cycles first through its fields, then the web field, and finally the web addresses.
Based on your script, I can't really determine what you are doing with each address so it finishes by collecting just the final part of each address in a list. The obscure parts for me are the pbpastes, the codes and the whole System Events block. This area would need tweaking.
Incidentally, it's quite likely that you can avoid some of the shell scripts but I can't say how yet. Obviously the script has some redundancies and could be further refined but I think it demonstrates how to extract the information you need. Take a look at it and let me know what issues there are that need addressing.
tell application "Microsoft Word"
set d1 to document "cardo_labels.docx"
set fContents to {} -- list of mergefield
set fResRange to {} -- list of result range, i.e. field merge data
repeat with x from 1 to (count of fields of d1)
set fcs to content of field code of field x of d1 --> " MERGEFIELD LastName "
set frr to content of result range of field x of d1 --> "Smith"
if fcs is not " NEXT " then -- ignore «Next Record»
set end of fContents to fcs
set end of fResRange to frr
end if
end repeat
--> single record example
fContents --> {" MERGEFIELD LastName ", " MERGEFIELD JobTitle ", " MERGEFIELD Company ", " MERGEFIELD City ", " MERGEFIELD Web "}
fResRange --> {"Smith", "President", "Acme Screw & Gear", "Metz", "http://zotero.org/users/1234/items/smith-metz"}
-- NB when not displaying 'merged data', fResRange will appear thusly: {"«LastName»", "«JobTitle»", "«Company»", "«City»", "«Web»"}
set webList to {}
repeat with y from 1 to (count of fResRange)
if item y of fResRange begins with "http://zotero.org/users/" then
set end of webList to (item y of fResRange)
end if
end repeat
--> {"http://zotero.org/users/1234/items/smith-metz"}
--> {"http://zotero.org/users/1234/items/smith-metz", "http://zotero.org/users/4222/items/branson-metz", "http://zotero.org/users/3236/items/house-metz", "http://zotero.org/users/3342/items/kurtz-london", "http://zotero.org/users/12345/items/jones-london"}
set urlPiece to {}
set AppleScript's text item delimiters to "/"
repeat with z in webList
set end of urlPiece to last text item of z
end repeat
-- contents of z
--> "http://zotero.org/users/1234/items/smith-metz"
set AppleScript's text item delimiters to ""
urlPiece
--> {"smith-metz"}
--> {"smith-metz", "jones-saopaolo", "branson-metz", "house-metz", "kurtz-london", "jones-london"}
end tell
Thanks to ideas from #Mockman.
Combining with the selection, here is the way to extract text from selected field code via AppleScript:
tell application "Microsoft Word"
tell selection
set fcs to content of field code of field of text object
end tell
end tell
fcs
I have a folder filled with pdf files.
filename_1.pdf
filename_2.pdf
filename_3.pdf
etc...
I am looking for a way to go from those filenames to something like :
filename_1973878763487.pdf
filename_27523765376346.pdf
filename_326537652376523.pdf
I came across the following script that changes filenames to random numbers :
tell application "Finder"
repeat with this_item in (get items of window 1)
set name of this_item to ((random number from 1000 to 9999) & "." & name extension of this_item) as string
end repeat
end tell
The script outputs something like this :
3598.pdf
7862.pdf
8365.pdf
So i need a way to append the random numbers to the original filename.
This should work for you
tell application "Finder"
repeat with thisItem in (get items of window 1)
set fileName to name of thisItem
tell current application
set theOffset to offset of "_" in fileName
end tell
set tempFileName to text 1 thru (theOffset + 1) of fileName
tell current application
set randomNumber to (random number from 1000 to 9999)
end tell
set name of thisItem to tempFileName & (randomNumber & "." & name extension of thisItem) as string
end repeat
end tell
I am brand new to Applescript. I would like a script that would list the artist and the number of songs in that artist's folder. I would like to do it just for artists whose names starts with A. When I am ready, I would then get the list for artist whose names starts with B, and so on. I did find this post: "What's the fastest way in iOS to retrieve the number of songs for a specific artist?" Maybe that script would work but I don't know how to modify this line "if (artistName != nil)" to get what I want. Also, I don't know where the information is stored so I can retreive it "// store the new count
[artists setObject:[NSNumber numberWithInt:numSongs] forKey:artistName]; Oh, and I am not using iOS I will be using osx. Perhaps I could modify this script that I found. It gets the number of albums by artist.
MPMediaQuery *albumQuery = [MPMediaQuery albumsQuery];
NSArray *albumCollection = [albumQuery collections];
NSCountedSet *artistAlbumCounter = [NSCountedSet set];
[albumCollection enumerateObjectsUsingBlock:^(MPMediaItemCollection *album, NSUInteger idx, BOOL *stop) {
NSString *artistName = [[album representativeItem] valueForProperty:MPMediaItemPropertyArtist];
[artistAlbumCounter addObject:artistName];
}];
NSLog(#"Artist Album Counted Set: %#", artistAlbumCounter);
I appreciate any help that you can offer. Thanks!
It makes no sense to look at iOS code and ObjectiveC at that in order to figure out what you should do with Applescript! In any case, here is what you want.
tell application "iTunes"
# Get playlist currently selected
set myPlayList to view of window 1
set s to (every track in myPlayList whose artist begins with "g")
repeat with t in s
log name of t
end repeat
log (count of s)
end tell
This one uses the selected playlist (or, if that fails for some reason, the whole library) and goes from A to Z. Replace the log parts with your code. To see how it works make sure in Script-Editor it shows the Log and for a better view select the Messages tab. Only file tracks are handled.
tell application "iTunes"
try
set selectedPlayList to view of window 1
on error
beep
set selectedPlayList to (container of browser window 1) -- whole library (I think)
end try
end tell
set totalItems to 0
repeat with i from (id of "A") to (id of "Z")
set thisLetter to (character id i)
log "-----------------------------------------------------------"
tell application "iTunes"
try
set currentItems to (file tracks in selectedPlayList whose artist begins with thisLetter)
set countItems to number of items in currentItems
set totalItems to totalItems + countItems
set s to "s"
if countItems = 1 then set s to ""
log (countItems as text) & " item" & s & " for artists starting with the letter " & quoted form of thisLetter
log "-----------------------------------------------------------"
repeat with i from 1 to countItems
set thisItem to item i of currentItems
tell thisItem -- this is like "tell file track x". Shortens the code because we can use "artist" instead of "artist of thisItem"
log (i as text) & ". " & quoted form of (get artist) & " | " & quoted form of (get name) & " [ " & time & " ] "
end tell
end repeat
on error the error_message number the error_number
beep
display dialog "Error: " & the error_number & ". " & the error_message buttons {"OK"} default button 1
return
end try
end tell
end repeat
log "-----------------------------------------------------------"
log "Items: " & totalItems as text
I am trying to build a script that sends me updates and notifications from cex.io. Please keep on reading below, so I may guide you until the point I have trouble with.
The first simple script in this operation goes to cex.io's trading page for BTC/GHS. It records ands saves the text to a file every 4 seconds. It works great. It doesn't need to have safari refresh because the site pushes info to the browser live.
repeat
set the webpage_content to ""
tell application "Safari" to set the webpage_content to the text of document 1
set theText to webpage_content
set a to "Macintosh HD:Users:PRIVATE:Desktop:CEX:"
set theFile to (open for access file ((a) & "CEXRaw") with write permission)
write theText to theFile
close access theFile
delay 4
end repeat
-
And it returns this in a main file every 4 seconds: (note I cut off a chunk from the bottom and the top of the file, because they are unimportant)
GHS:
0.05233439
BTC:
0.00000223
NMC:
0.00002939
LTC:
0.00000000
GHS/BTC
0.02362958 LTC/BTC
0.02438131 NMC/BTC
0.00597565 GHS/NMC
3.96951800 BF1/BTC
1.67000000 Fund Account
GHS/BTC
Last price:
0.02362958
Daily change:
-0.00018042
Today's open:
0.02381000
24h volume:
73812.35539255
-
I now need an applescript to read that file, and return wanted values. But I'm lost on how to write it.
It needs to find the number under BTC, and set it as a variable.
It needs to find the number under GHS, and set it as a variable.
It needs to find the number under Last Price, and set it as a variable.
If anyone could script that really quick for me, or tell me how to do it, that would be amazing. Thank you so much!
Well, if those values will always be in the same paragraph counts, you could just pull them by line number.
set theCEXRaw to read file "Macintosh HD:Users:PRIVATE:Desktop:CEX:CEXRaw"
set theGHS to paragraph 2 of theCEXRaw
set theBTC to paragraph 4 of theCEXRaw
set thePRICE to paragraph 17 of theCEXRaw
You'd need to adjust the paragraph numbers. But, assuming that paragraph numbers aren't reliably consistent, in pure Applescript, you'd use Applescript's Text Item Delimiters.
set theCEXRaw to read file "Macintosh HD:Users:PRIVATE:Desktop:CEX:CEXRaw"
set AppleScript's text item delimiters to {("GHS:
"), ("BTC:
"), ("Last price:
")}
set theCEXRaw to text items of theCEXRaw
set theGHS to paragraph 1 of item 2 of theCEXRaw
set theBTC to paragraph 1 of item 3 of theCEXRaw
set thePRICE to paragraph 1 of item 4 of theCEXRaw
Note that the three delims include a return character inside the quotes. You will want to capture the old delimiter first, so you can restore it, and hopefully you can do the setting of the delimiter outside your repeat loop to save juice.
You could also use do shell script with sed or grep to strip each value.
You could get those values using the offset which searches a string for a substring and returns it's character position.
eg, set pos to the offset of "world" in "hello world" -- returns 7
Here is a solution that uses this principal to find your values and convert them into the Applescript floating point type Number
property line_delimiter : linefeed -- OR return OR return & linefeed pending your data
set results to "GHS:
0.05233439
BTC:
0.00000223
NMC:
0.00002939
LTC:
0.00000000
Last price:
0.02362958"
processCEX(results)
on processCEX(in_text)
set btc_val to searchNumberValueLine("BTC:" & line_delimiter, in_text)
set ghs_val to searchNumberValueLine("GHS:" & line_delimiter, in_text)
set last_price_val to searchNumberValueLine("Last price:" & line_delimiter, in_text)
display dialog ("btc = " & btc_val & return & "ghs = " & ghs_val & return & " last price = " & last_price_val)
end processCEX
on searchNumberValueLine(key_name, input_str)
set start_index to the offset of key_name in input_str
if (start_index is not 0) then
set input_str to text (start_index + ((length of key_name))) thru -1 of input_str
set end_index to the offset of line_delimiter in input_str
if (end_index is 0) then
return input_str as number
else
return (text 1 thru (end_index - 1) of input_str) as number
end if
else
return -1
end if
end searchNumberValueLine
Also i'd recommend against writing to a text file if you don't need to, to avoid any file io issues when reading the same file from a different script, given you are modifying it every 4 seconds.
You could change your code to something like this:
repeat
set the webpage_content to ""
tell application "Safari" to set the webpage_content to the text of document 1
processCEX(webpage_content)
delay 4
end repeat
I'm trying to make an AppleScript droplet to rename a bunch of images annoyingly formatted, but I found out my AppleScript skills have become nonexistent and I'm getting nowhere. So if possible, full code, not just snippets.
The file setup is always the same, but there are many variations (ex: Yellowst.Nat.Park.D12P55.DMS.3248.jpg)
It starts with a place name, should be a find and replace for a bunch of different strings, ("Yellowst.Nat.Park" -> "Yellowstone National Park")
Then it is followed by two numbers that should be changed in format (D12P55 -> [12x55]). They're always set up in a "D" followed by two numbers, a "P" and again two numbers.
And it ends with a random string, can be numbers, letters etc, which all have to go. They differ in format and length, no pattern in them.
Basically I want to go from "Yellowst.Nat.Park.D12P55.DMS.3248.jpg" to "Yellowstone National Park [02x03] .jpg" I want to add text afterwards so want to end with a space.
The best way to do this seems to me a repetitive find and replace for the first part, Make a list for a bunch of terms wich have to be replaced by a bunch of respective terms. Followed by a detection of the number format and ending with deleting of the random string after it.
Here is another approach.
property pictureFolder : (alias "Mac OS X:Users:Sam:Pictures:test:")
property findList : {"Yellowst.Nat.Park", "Jellyst.Nat.Park"}
property replaceList : {"Yellowstone National Park", "Jellystone \\& National Park"}
tell application "System Events"
set nameList to (name of every file of pictureFolder whose visible = true)
repeat with i from 1 to count of (list folder pictureFolder without invisibles)
set fileName to item i of nameList
set fileExtension to (name extension of (file fileName of pictureFolder))
repeat with j from 1 to count of findList
if fileName contains item j of findList then
set tempName to do shell script "echo " & fileName & " | sed 's/.D\\([0-9][0-9]\\)P\\([0-9][0-9]\\).*/[\\1x\\2] " & i & "." & fileExtension & "/'"
set tempName to do shell script "echo " & tempName & " | sed 's/^" & item j of findList & "/" & item j of replaceList & " /'"
set name of (file fileName of pictureFolder) to tempName
exit repeat
else if j = (count of findList) then
set tempName to do shell script "echo " & fileName & " | sed 's/[.]/ /g'"
set tempName to do shell script "echo " & tempName & " | sed 's/.D\\([0-9][0-9]\\)P\\([0-9][0-9]\\).*/ [\\1x\\2] " & i & "." & fileExtension & "/'"
set name of (file fileName of pictureFolder) to tempName
end if
end repeat
end repeat
end tell
To avoid duplicate names, I added a counter to the end of the file name. If there are no duplicates, you can use this instead:
set tempName to do shell script "echo " & fileName & " | sed 's/.D\\([0-9][0-9]\\)P\\([0-9][0-9]\\).*/[\\1x\\2] " & "." & fileExtension & "/'"
I like small challenges like this Sam. They're fun to me... maybe I'm sick ;). Anyway, I wrote you a handler to clean the file name as you requested. It's not really hard to manipulate text in applescript if you're comfortable with text item delimiters and such. These small challenges keep my text skills sharp.
NOTE: in the nameList property the name must end with a period or whatever character is just before the letter D in the number sequence DxxPxx as you mentioned.
So give this a try. Plug in a variety of fileNames and ensure it works how you want. Of course you need to put more values into the nameList and nameReplaceList properties too.
property nameList : {"Yellowst.Nat.Park."}
property nameReplaceList : {"Yellowstone National Park"}
set fileName to "Yellowst.Nat.Park.D12P55.DMS.3248.jpg"
cleanFilename(fileName)
(*================ SUBROUTINES ================*)
on cleanFilename(fileName)
-- first find the base name and file extension of the file name
set tids to AppleScript's text item delimiters
set ext to ""
if fileName contains "." then
set AppleScript's text item delimiters to "."
set textItems to text items of fileName
set ext to "." & item -1 of textItems
set baseName to (items 1 thru -2 of textItems) as text
set text item delimiters to ""
else
set baseName to fileName
end if
-- next find the pattern D, 2 numbers, P, and 2 numbers in the baseName
set chars to characters of baseName
set theSequence to missing value
repeat with i from 1 to (count of chars) - 6
set thisChar to item i of chars
if thisChar is "d" and item (i + 3) of baseName is "p" then
try
set firstNum to text (i + 1) thru (i + 2) of baseName
firstNum as number
set secondNum to text (i + 4) thru (i + 5) of baseName
secondNum as number
set theSequence to text i through (i + 5) of baseName
exit repeat
end try
end if
end repeat
-- now make the changes
if theSequence is not missing value then
set AppleScript's text item delimiters to theSequence
set theParts to text items of baseName
set fixedFirstPart to item 1 of theParts
repeat with i from 1 to count of nameList
if item i of nameList is fixedFirstPart then
set fixedFirstPart to item i of nameReplaceList
exit repeat
end if
end repeat
set fixedName to fixedFirstPart & " [" & firstNum & "x" & secondNum & "]" & ext
else
set fixedName to fileName
end if
set AppleScript's text item delimiters to tids
return fixedName
end cleanFilename
Now if you want to automate this for a folder full of files you can use this code. Just replace lines 3 and 4 of the above script with this. I didn't check this code but it's simple enough it should work as-is.
NOTE: you don't need to worry if non-image files are in the folder you choose with this code because they won't (I'm assuming this) have the DxxPxx number sequence and thus this script will not change them in any way.
set theFolder to choose folder
tell application "Finder"
set theFiles to files of theFolder
repeat with aFile in theFiles
set thisName to name of aFile
set newName to my cleanFilename(thisName)
if newName is not thisName then
set name of aFile to newName
end if
end repeat
end tell