Applescript: Break a set of lines into blocks based on a condition - applescript

I have an Automator service for uploading images and returning URLs to a text editor.
It works very well, but there's something I want to improve:
When the workflow starts, Automator will get all images in a folder and upload them to an FTP server.
Then it returns a result like below:
("http://url/0530/pic01/pic-01.jpg",
"http://url/0530/pic01/pic-02.jpg",
"http://url/0530/pic01/pic-03.jpg",
"http://url/0530/pic01/pic-04.jpg",
"http://url/0530/pic02/pic-01.jpg",
"http://url/0530/pic02/pic-02.jpg",
"http://url/0530/pic02/pic-03.jpg",
"http://url/0530/pic02/pic-04.jpg",
"http://url/0530/pic03/pic-01.jpg",
"http://url/0530/pic03/pic-02.jpg",
"http://url/0530/pic03/pic-03.jpg",
"http://url/0530/pic03/pic-04.jpg")
And the workflow gets these strings and puts them in a new text document.
Finally, here is the result in a text editor:
http://url/0530/pic01/pic-01.jpg
http://url/0530/pic01/pic-02.jpg
http://url/0530/pic01/pic-03.jpg
http://url/0530/pic01/pic-04.jpg
http://url/0530/pic02/pic-01.jpg
http://url/0530/pic02/pic-02.jpg
http://url/0530/pic02/pic-03.jpg
http://url/0530/pic02/pic-04.jpg
http://url/0530/pic03/pic-01.jpg
http://url/0530/pic03/pic-02.jpg
http://url/0530/pic03/pic-03.jpg
http://url/0530/pic03/pic-04.jpg
But I want it to be:
http://url/0530/pic01/pic-01.jpg
http://url/0530/pic01/pic-02.jpg
http://url/0530/pic01/pic-03.jpg
http://url/0530/pic01/pic-04.jpg
http://url/0530/pic02/pic-01.jpg
http://url/0530/pic02/pic-02.jpg
http://url/0530/pic02/pic-03.jpg
http://url/0530/pic02/pic-04.jpg
http://url/0530/pic03/pic-01.jpg
http://url/0530/pic03/pic-02.jpg
http://url/0530/pic03/pic-03.jpg
http://url/0530/pic03/pic-04.jpg
I think I can use AppleScript in Automator to do this before the result is sent to the text editor.
Do you have any coding advice?
===================================================
Thanks # user309603 and # mklement0 so much!!
I choose pure applescript method.
Here is my code in automator that run applescript in workflow:
on run {input, list}
set txtG to first item of input
repeat with txtLine in items 2 thru -1 of input
if txtLine contains "-01" then set txtG to txtG & linefeed
set txtG to txtG & linefeed & txtLine
end repeat
return txtG
end run

Here is a pure applescript solution.
I would prefer mklement0's awk-solution. It is much faster if you have long URL-lists.
set txt to "http://url/0530/pic01/pic-01.jpg
http://url/0530/pic01/pic-02.jpg
http://url/0530/pic01/pic-03.jpg
http://url/0530/pic02/pic-01.jpg
http://url/0530/pic03/pic-01.jpg
http://url/0530/pic03/pic-02.jpg
http://url/0530/pic03/pic-03.jpg
http://url/0530/pic03/pic-04.jpg
http://url/0530/pic04/pic-01.jpg"
set txtG to first paragraph of txt
repeat with txtLine in paragraphs 2 thru -1 of txt
if txtLine contains "-01" then set txtG to txtG & linefeed
set txtG to txtG & linefeed & txtLine
end repeat
return txtG

The following AppleScript snippet demonstrates the approach you can use in principle - I'm unclear on the exact circumstances:
If you must process the raw result:
# Sample input text.
set txt to "(\"http://url/0530/pic01/pic-01.jpg\",
\"http://url/0530/pic01/pic-02.jpg\",
\"http://url/0530/pic01/pic-03.jpg\",
\"http://url/0530/pic01/pic-04.jpg\",
\"http://url/0530/pic02/pic-01.jpg\",
\"http://url/0530/pic02/pic-02.jpg\",
\"http://url/0530/pic02/pic-03.jpg\",
\"http://url/0530/pic02/pic-04.jpg\",
\"http://url/0530/pic03/pic-01.jpg\",
\"http://url/0530/pic03/pic-02.jpg\",
\"http://url/0530/pic03/pic-03.jpg\",
\"http://url/0530/pic03/pic-04.jpg\")"
# Group (break into blocks) by files containing "-01."
set txtGrouped to do shell script ¬
"printf %s " & quoted form of txt & " | tr -d '()\"'" & ¬
" | awk -F, 'NR>1 && /-01\\./ { print \"\" } { print $1 }'" ¬
without altering line endings
If you already have a cleaned-up set of URL-only lines:
# Sample input text.
set txt to "http://url/0530/pic01/pic-01.jpg
http://url/0530/pic01/pic-02.jpg
http://url/0530/pic01/pic-03.jpg
http://url/0530/pic01/pic-04.jpg
http://url/0530/pic02/pic-01.jpg
http://url/0530/pic02/pic-02.jpg
http://url/0530/pic02/pic-03.jpg
http://url/0530/pic02/pic-04.jpg
http://url/0530/pic03/pic-01.jpg
http://url/0530/pic03/pic-02.jpg
http://url/0530/pic03/pic-03.jpg
http://url/0530/pic03/pic-04.jpg"
# Group (break into blocks) by files containing "-01."
set txtGrouped to do shell script ¬
"printf %s " & quoted form of txt & ¬
" | awk 'NR>1 && /-01\\./ { print \"\" } { print }'" ¬
without altering line endings
Uses do shell script to have awk perform the desired grouping.
Note:
without altering line endings is required to prevent AppleScript from replacing \n chars in the output with Mac-style \r line endings.
The result will have a trailing \n char, even if the input didn't. To fix this, use:
set txtGrouped to text 1 thru ((length of txtGrouped) - 1) of txtGrouped

If the goal is to always divide the list items into paragraphs grouped by four, here is an applescript you can put in an automator action:
set l to input as list
set r to ""
repeat with n from 1 to (count l) by 4
set r to r & item n of l & return & item (n + 1) of l & return & item (n + 2) of l & return & item (n + 3) of l & return & return
end repeat
return r
Clarify if instead what you need is to group all the versions of one pic together, but it won't always be 4 each, and that the script needs to check the file names to determine.

Here is a solution : This script checks the name of the parent folder for each file, when the folder name is not the same, it add a blank line.
Append the Run Shell Script action into your workflow, select the "/bin/bash" shell and select "to stdin"
Put this script in the Run Shell Script action :
awk -F/ '{f=$(NF - 1); if (NR==1) {fName=f} else if (f != fName) {print ""; fName=f} print}' < "/dev/stdin"

Related

Get path to main iTunes library and play a song from it

I currently have an Applescript that lets you type in a song and play it.
Here it is:
set userInput to text returned of (display dialog "Type something" default answer "")
if userInput contains "Play " then
set {TID, text item delimiters} to {text item delimiters, {"Play "}}
if length of userInput is greater than or equal to 2 then set resultString to text item 2 of userInput
set text item delimiters to TID
set playSong to (resultString as string)
tell application "iTunes"
set mySongs to every track of library playlist 1 whose name is playSong
repeat with aSong in mySongs
play aSong
end repeat
if (count of mySongs) = 0 then
say "Song not found"
end if
end tell
end if
Basically, I need to get the path to the main iTunes library and play a song from it. Currently, to search for songs, iTunes has to open. And if it can't find the song, it just stays open. I want to search the actual iTunes directory to make it so if iTunes cannot find a song, it doesn't open
I have no idea how to do this.
Thanks
Here is the script to search in the "iTunes Library.xml" file.
set XMLFile to my get_iTunes_Library_xml()
set userInput to text returned of (display dialog "Type something" default answer "Play ")
if userInput begins with "Play " and length of userInput > 5 then
set playSong to text 6 thru -1 of userInput
set searchString to "<key>Name<\\/key><string>" & playSong & "<\\/string>" -- to match exact name
if (my searchTrackName(searchString, XMLFile)) is not "" then
tell application "iTunes" to play (tracks whose name is playSong)
else
say "Song not found"
end if
end if
on searchTrackName(t, f) -- search in iTunes Library.xml file
if "&" is in t then set t to do shell script "sed \"s/&/&/g\" <<<" & quoted form of t -- to replace "&" by "&"
try -- return a count of matching lines
return do shell script "grep -c -m1 -i " & (quoted form of t) & " " & f -- "-i" equal case insensitive, "-m 1" to exit at first match
end try
return ""
end searchTrackName
on get_iTunes_Library_xml() -- get the path
do shell script "defaults read com.apple.iApps iTunesRecentDatabases | sed -En 's:^ *\"(.*)\"$:\\1:p' |/usr/bin/perl -MURI -e 'print URI->new(<>)->file;'"
return quoted form of the result
end get_iTunes_Library_xml
The "com.apple.iApps.plist" file contains the path to yours iTunes libraries (if you have more than one), the script get the path of the "iTunes Library.xml" file of the current library.
Not a finished solution, but perhaps a starting point.
I didn't find a way to get automatically the path to the iTunes library.
With the StandardAdditions you can get the path to the main music folder in the home folder via
set searchPath to POSIX path of music folder
You can set the path manual, like this:
set searchPath to quoted form of "/Users/USERNAME/Music/iTunes/iTunes Music/"
To search for the music files without iTunes, i use the shell command "mdfind"
do shell script "mdfind -count -onlyin PATH SEARCHSTRING"
With the count-Flag we get the total numbers of matches. If you like to see what mdfind finds, omit the count-Flag.
tell application "System Events"
set userInput to text returned of (display dialog "Search for music" default answer "madonna")
set searchPath to POSIX path of music folder
end tell
set shellCommand to "mdfind -count -onlyin " & searchPath & " " & quoted form of userInput
set searchResult to (do shell script shellCommand) as number
if searchResult = 0 then
say "Song not found"
else if searchResult >= 1 then
say "Found some songs"
end if
With mdfind you can search in the metadata, for example you can search for only MP3-Files:
mdfind "kMDItemContentType=='public.mp3'"

Strip file path info to • and / text item delimiter

The script below basically you choose a folder with PDFs, get file count of PDFs on chosen folders, write the results in text file, open the text file in Excel. The scripts works fine but I get entire the file path.
Results are:
/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/BODY/: 65
/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/BODY/: RESENDS 0
/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/COVERS/: 23
/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/COVERS/: RESENDS 6
I want to strip everything before the bullet • then for every / a column. Something like this:
CUSTO_4 BODY 65
CUSTO_4 BODY RESENDS 0
CUSTO_4 COVERS 23
CUSTO_4 COVERS RESENDS 6
I trying to grasp the concept of text item delimiters and using the offset command but I don't know how to implement that into the script.
set target_folder to choose folder with prompt "Choose target folders containing only PDFs to count files" with multiple selections allowed without invisible
set results to ""
repeat with i from 1 to (count target_folder)
set thisFolder to (POSIX path of item i of target_folder)
--Find & count all PDFs in folders selected that DON'T starts with letter R
set fileCount to do shell script "find " & quoted form of thisFolder & " -type f -name *.pdf -and -not -iname 'R[0-9-_]*.pdf' | wc -l"
set results to (results & "" & thisFolder & ":" & fileCount & return)
--Find & count all PDFs in folders selected that starts with letter R
set fileCount to do shell script "find " & quoted form of thisFolder & " -type f -iname 'R[0-9-_]*.pdf' | wc -l"
set results to (results & "" & thisFolder & ":" & tab & tab & "RESENDS" & fileCount & return)
end repeat
--write results to a txt file
set theFilePath to (path to desktop folder as string) & "PDF File Count.txt"
set theFile to open for access file theFilePath with write permission
try
set eof of theFile to 0
write results to file theFilePath
close access theFile
on error
close access theFile
end try
--Will open the the PDF File Count.txt in Excel
tell application "Microsoft Excel"
activate
open text file filename "PDF File Count.txt"
end tell
AppleScript's text item delimiters are used to determine how text is broken apart and/or reassembled. When you get the text items of a string, the string is broken apart at each delimiter, and the result is a list of the pieces. Going the other way, if you coerce a list of text items to a string, the pieces are reassembled with the delimiter used in between each piece.
For your example, you could use something like the following (I added a little formatting to get your result):
set theList to {¬
"/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/BODY/: 65", ¬
"/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/BODY/: RESENDS 0", ¬
"/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/COVERS/: 23", ¬
"/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/COVERS/: RESENDS 6"}
set finalResult to {} -- this will be the final result
set tempTID to AppleScript's text item delimiters -- stash the original delimiters
repeat with anItem in theList
set AppleScript's text item delimiters to "•"
set pieces to text items of anItem -- break apart at bullets
log result
set theFile to (rest of pieces) as text -- drop the first piece and reassemble
set AppleScript's text item delimiters to "/"
set pieces to text items of theFile -- now break apart at slashes
log result
set lastPiece to last item of pieces -- trim the last piece a bit
set theCount to 0
repeat while first character of lastPiece is in {space, ":"}
set lastPiece to text 2 thru -1 of lastPiece -- trim it
set theCount to theCount + 1 -- count up trimmed characters
end repeat
if theCount > 4 then set lastPiece to tab & tab & lastPiece -- add a little formatting...
set last item of pieces to lastPiece -- put the trimmed piece back
set text item delimiters to tab & tab
set pieces to pieces as text -- put the pieces back together with tabs
log result
set end of finalResult to pieces -- store the reassembled text for later
end repeat
set AppleScript's text item delimiters to tempTID -- restore the original delimiters
choose from list finalResult with empty selection allowed -- show the results
You don't always have to use text item delimiters to manipulate text:
set xxx to "/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/BODY/: 65
/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/BODY/: RESENDS 0
/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/COVERS/: 23
/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/COVERS/: RESENDS 6"
set yyy to do shell script "echo " & quoted form of xxx & " | grep -o •.* | sed -e 's/•\\(.*\\):\\(.*\\)/\\1\\2/' -e 's/\\// /'g"
and the other approach:
set xxx to "/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/BODY/: 65
/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/BODY/: RESENDS 0
/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/COVERS/: 23
/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•CUSTO_4/COVERS/: RESENDS 6"
-- break apart and capture original delimiters
set {Astid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "/Volumes/PREPRESS/1_CATALOG/2_Press/PRINT_Catalog/2012/•"}
set yyy to text items 2 thru -1 of xxx
--put together
set AppleScript's text item delimiters to {""}
set yyy to yyy as string
-- break apart
set AppleScript's text item delimiters to ":"
set yyy to text items of yyy
--put together
set AppleScript's text item delimiters to {""}
set yyy to yyy as string
-- break apart
set AppleScript's text item delimiters to "/"
set yyy to text items of yyy
--put together
set AppleScript's text item delimiters to tab
set yyy to yyy as string
-- reset original delimiters
set AppleScript's text item delimiters to Astid
return yyy

Get part of string in Applescript

I try to make a applescript that read files in a folder and takes only part of the filename. The files would look like this: the.name.of.a.tv.show.s01e01
I could search for s01 but then i have to make a rule for every season that can come.
Is there some way to look for s--e-- and then take the part of the filename before that?
Try:
set xxx to "the.name.of.a.tv.show.s01e01 etc etc"
set yyy to (do shell script "echo " & xxx & " | sed 's/.s[0-9][0-9]e[0-9][0-9].*//'")
return yyy
Incorporating your previous question:
set seasonList to {}
repeat with aShow in listOfShows
set aShow to aShow as string
set end of seasonList to (do shell script "echo " & aShow & " | sed 's/.s[0-9][0-9]e[0-9][0-9].*//'")
end repeat
return seasonList

Read folder, parse filenames and call other program

In brief, I need to do something like this:
I have a folder with a lot of files and want to process all files with extension .epub.
All files already follow a naming scheme: Lastname, Firstname - Title.epub or Lastname, Firstname - Series x - Title.epub and I need a parser for Lastname, Firstname, Series (if existing) and Title.
I have a command-line tool that sets metadata: ebook-meta filename -a "Firstname Lastname" -t Title
There are many snipplets for 1.), however I am in need for input for 2.) and appreciate any help/pointers!
You can start with the following and change it to meet your needs. It compiles, although untested.
set p to POSIX file "/Users/kaass/Desktop/test/"
tell application "Finder" to set filelist to name of every file of folder p
repeat with filename in filelist
set text item delimiters to ""
if text -5 thru -1 of filename is equal to ".epub" then
set temp to items 1 thru -6 of filename as text
set text item delimiters to " - "
set myWord to text items 1 thru -1 of temp
set title to myWord's last item as text
if myWord's length is equal to 3 then set series to myWord's second item as text
set myWord to item 1 of myWord as text
if myWord contains "," then
set text item delimiters to ", "
else
set text item delimiters to " "
end if
set author to (text item 2 of myWord) & space & (text item 1 of myWord)
set path_and_filename to POSIX path of file p & filename
do shell script "echo Processing file " & quoted form of path_and_filename & ": " & author & " +++ " & title
do shell script "/Applications/calibre.app/Contents/MacOS/ebook-meta " & quoted form of path_and_filename & " -a " & quoted form of author & " -t " & quoted form of title
end if
end repeat
Just comment if you need something to be changed.

Applescript- For every item that grep finds

This code obviously won't work but I'm looking for a syntax change to make it work.
for every item that grep finds
set myCommand to do shell script "grep -w word test.log"
set mySecondCommand to do shell script "grep -w end test.log"
end
The following output should be correct (What I want):
word
end
word
end
instead I get because I do not have this theoretical "for every item that grep finds" statement (I don't want this output):
word
word
end
end
Your initial grep results will be in string format eg. one long string. In order to iterate them you will need to turn the string into a list, thus I use the "paragraphs" command. Once you have the initial grep results in list format, then you can use a repeat loop to process the items in the list. When you process the items you will need to store those results in a new list so that at the end of the script you can view the results in total. Something like this...
set firstWord to "word"
set secondWord to "end"
-- use the ls command and grep to find all the txt documents in your documents folder
set aFolder to (path to documents folder) as text
set grepResults to do shell script "ls " & quoted form of POSIX path of aFolder & " | grep \"txt\""
set grepResultsList to paragraphs of grepResults
-- search the found txt documents for the words
set totalResults to {}
repeat with aResult in grepResultsList
set thisPath to aFolder & aResult
try
set myCommand to paragraphs of (do shell script "grep -w " & firstWord & space & quoted form of POSIX path of thisPath)
set myCommandCount to count of myCommand
set end of totalResults to {thisPath, firstWord, myCommandCount, myCommand}
end try
try
set mySecondCommand to paragraphs of (do shell script "grep -w " & secondWord & space & quoted form of POSIX path of thisPath)
set mySecondCommandCount to count of mySecondCommand
set end of totalResults to {thisPath, secondWord, mySecondCommandCount, mySecondCommand}
end try
end repeat
return totalResults

Resources