3

I have a .txt file saved on my computer. I want my Automator application to add a bit of text to the .txt file (the text will be entered by the user). I already know how to append text or prepend text in AppleScript. However, I want the text to be inserted into a specific location.

For example, this is the contents of my .txt file entitled My Fruit Log.txt. This is what the .txt file looks like before the text is written to the file:

You can see where exactly I want the text to be saved in the file in this image:

Is what I want to do clear? I want the text to be written on the line directly above the first blank line found in the file. Note: It is not necessarily the second line from the top where I want the text to be written. Depending on what text has already been written to the file, the text might be saved on a lower line. For example:

The location where I want the text to be written must be at least the second line from the top, but it may also be as further down as the seventh line from the top. So, the most reliable way to articulate where I want to write the text is "on the line before the first instance of a blank line in the document."

Can this be accomplished in AppleScript?

  • You said "So, the most reliable way to articulate where I want to write the text is "on the line before the first instance of a blank line in the document."", well that's not what the images show where your wrote "I ate a coconut at 10 am. was in between two lines that didn't have a blank line between them. So what is it that you really want? – user3439894 Nov 9 '16 at 5:04
  • @user3439894 No, the images are correct. The second image is to explain that the line to be entered isn't always the second line, but rather the line indicated by "This is the location…". – grg Nov 9 '16 at 8:54
  • @user3439894 In the second image, I don't want the text to be written where it says, "I ate a coconut at 10 am." I want the text to be written where it says, "This is the location where I want the AppleScript to write to." It may be the second line from the top, or it may be the fourth line from the top. The number of lines from the top varies, but the location will always be directly above the first instance of a blank line. What grgarside wrote is correct. – rubik's sphere Nov 9 '16 at 13:33
2

Here's a shell script:

sed -i '' -e ':a' -e 'N' -e '$!ba' -e 's/\n\n/\
Write the new line you wish inserted in your file here\
\
/' ~/Desktop/file.txt

You can wrap this in a ‘do shell script’ if you really want AppleScript, but for an Automator script, you can use a Run Shell Script action and just use the shell script.


Here's an AppleScript wrapper for the script, where the TextToWrite variable and the Target_Filepath variable have been defined elsewhere per your comments:

set addline to "sed -i '' -e ':a' -e 'N' -e '$!ba' -e 's/\\n\\n/\\
" & TextToWrite & "\\
\\
/' \"" & Target_Filepath & "\""
do shell script addline
  • Can you show how to do this in AppleScript? I have a rather convoluted code, so it would be much easier to implement if it is in AppleScript, as opposed to a Run Shell Script action. Also, what edits to the code are necessary if the text to write is a variable (e.g., a string entitled TextToWrite instead of the actual text like you've provided)? – rubik's sphere Nov 9 '16 at 17:14
  • I've tried writing do shell script followed by your whole code in double quotes, but I get an error. So I assume converting your code to AppleScript is not as simple as that (unless I made an obvious mistake... which is likely). – rubik's sphere Nov 10 '16 at 2:29
  • @rubik'ssphere I've added an AppleScript wrapper to my answer and used the value of the TextToWrite variable in the script. – grg Nov 10 '16 at 8:39
  • It works great! What edits to the code are necessary if the file path is a variable and this variable contains spaces? E.g., a string entitled Target_Filepath that contains the text: /Users/Me/Desktop/November_My Fruit Log.txt – rubik's sphere Nov 14 '16 at 8:11
  • @rubik'ssphere I've edited my answer to include that variable too. I encourage you to take a look at some AppleScript documentation — you can start at the AppleScript Fundamentals guide. – grg Nov 14 '16 at 8:35
1

If I understand your question correctly, you what to write some new text content to the text file directly above the first blank line and if that's correct then here's an example of one way it can be done.

Note that sometimes the AppleScript do shell script command can get complex when having to escape certain instances of special charters, ordinary charters and or if multiple command lines are involved, etc.

So in the following example I'm going to limit the do shell script command to something as simple as I can that doesn't require lots of escaping while allowing for a variable filename and will return the byte count up to the first blank line in the file, as I believe this is the insertion point you're requesting for where the new text is to be written.

I will then use the byte count as the offset point as the reference point to where the new text would be written to the target text file. I'll do this by reading into variables from the start of the file up the offset and reading from the offset to the end of the file, then concatenate the three variables to one variable to write to the target file from the beginning of the file. Thus overwriting the old content with the combination of new and old content.


AppleScript code:

set filePathName to POSIX path of (path to desktop as string) & "My Fruit Log.txt"

try
    set offsetCount to (do shell script "grep -b -m1 '^$' \"" & filePathName & "\" | cut -f1 -d:")
end try
if offsetCount is equal to "0" or offsetCount is equal to "" then
    display dialog "The contents of the target file does not conform to the necessary requirements for processing and or may contain consecutive 0D Carriage Return Characters, instead of the 0A Line Feed Characters expected by default in macOS." buttons {"OK"} default button 1
    return
end if

set newContent to "I ate a strawberry at 1 am."

try
    set referenceNumber to open for access filePathName with write permission

    set oldContentUpToFirstBlankLine to read referenceNumber from 1 to offsetCount
    set oldContentFromFirstBlankLine to read referenceNumber from offsetCount to eof

    set allContent to oldContentUpToFirstBlankLine & newContent & oldContentFromFirstBlankLine

    write allContent to referenceNumber starting at 0
    close access referenceNumber

on error eStr number eNum
    display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with title "File I/O Error..." with icon caution
    try
        close access referenceNumber
    end try
    return
end try

Terminal output of "My Fruit Log.txt" before running AppleScript code:

$ cat "$HOME/Desktop/My Fruit Log.txt"
2016_11_09 -

2016_11_08 -
I ate a banana at 8 am.
I ate a kiwi at 11 am.
I ate a mango at 6 pm.

2016_11_07 -
I ate a pear at 6 am.
I ate a tangerine at 4 pm.
I ate a peach at 8 pm.
$ 

Terminal output of "My Fruit Log.txt" after running AppleScript code:

$ cat "$HOME/Desktop/My Fruit Log.txt"
2016_11_09 -
I ate a strawberry at 1 am.

2016_11_08 -
I ate a banana at 8 am.
I ate a kiwi at 11 am.
I ate a mango at 6 pm.

2016_11_07 -
I ate a pear at 6 am.
I ate a tangerine at 4 pm.
I ate a peach at 8 pm.
$ 

So as you can see, this inserts the new text content above the first blank line in the file.

Below we see the Event Log of the AppleScript Editor when the above AppleScrip code is run:

tell current application
    path to desktop as string
        --> "Macintosh HD:Users:me:Desktop:"
    do shell script "grep -b -m1 '^$' \"/Users/me/Desktop/My Fruit Log.txt\" | cut -f1 -d:"
        --> "13"
    open for access "/Users/me/Desktop/My Fruit Log.txt" with write permission
        --> 172
    read 172 from 1 to "13"
        --> "2016_11_09 -
"
    read 172 from "13" to eof
        --> "

2016_11_08 -
I ate a banana at 8 am.
I ate a kiwi at 11 am.
I ate a mango at 6 pm.

2016_11_07 -
I ate a pear at 6 am.
I ate a tangerine at 4 pm.
I ate a peach at 8 pm.
"
    write "2016_11_09 -
I ate a strawberry at 1 am.

2016_11_08 -
I ate a banana at 8 am.
I ate a kiwi at 11 am.
I ate a mango at 6 pm.

2016_11_07 -
I ate a pear at 6 am.
I ate a tangerine at 4 pm.
I ate a peach at 8 pm.
" to 172 starting at 0
    close access 172
end tell
  • You understood me correctly. Question: How does your code differ, functionally, from grgarside's code? Both codes produce the same effect... is one code "superior" than the other in some way? – rubik's sphere Nov 14 '16 at 8:15
  • @rubik's sphere, I posted my answer 2 days ago when it looked like you were having issues with grgarside's answer, based in part on the comments, so you'd have an alternative... although he did edit his answer today. Suffice it to say there's usually more then one way to code anything and generally speaking it doesn't necessarily mean one way is superior to the other if it works for your needs and you understand what and how it's doing it and why you might choose one method over the other. I strongly echo grgarside's comment "I encourage you to take a look at some AppleScript documentation". – user3439894 Nov 14 '16 at 14:18
  • When I run your code, I get: "The action “Run AppleScript” encountered an error. File permission error." I am the administrator. I've right-clicked the .txt file in Finder, clicked "Get Info", and then set the "Privilege" for "Me","staff", and "everyone" to "Read & Write". I still get the error; nothing is written to file. – rubik's sphere Nov 22 '16 at 23:30
  • Can you please download my .txt file and see if your code works properly on your computer @user3439894? I am unable to run your code without error and the newContent text is never written to my .txt file. I am presented with one of the following error messages: "File is already open.", "End of file error.", or "File permission error." – rubik's sphere Nov 25 '16 at 6:33
  • @rubik's sphere, This is not working for you due to the same issue with another resent question of yours that I answered, being 0D0D instead of what it's supposed to be 0A0A. Also, you need to understand that code being presented is not necessarily all the code you you might need and is just proof of concept code! You are expected to build upon what's being presented by adding requisite code so it conforms not only to your specific needs/wants but also proper programing paradigms as well. Continued in next comment... – user3439894 Nov 25 '16 at 17:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .