2

I have a .txt file saved on my computer. The contents of the .txt file looks like this, for example:

I want my Automator application to read the first line of the .txt file and to put that line into a new variable. This is so that I can check if this variable matches another variable.

My ultimate goal is to have my application automatically write today's date to the top of the file and add an additional blank line beneath today's date. But I only want this to occur if today's date has not already been written to file, of course.

Here's the code that I have so far:

# Part 1
# Get and format today's date.

set TodayDate to current date
set y to text -4 thru -1 of ("0000" & (year of TodayDate))
set m to text -2 thru -1 of ("00" & ((month of TodayDate) as integer))
set d to text -2 thru -1 of ("00" & (day of TodayDate))
set FormattedTodayDate to y & "_" & m & "_" & d & " -"


# Part 2
# Get the first line of the .txt file.

set Target_Filepath to quoted form of "/Users/Me/Desktop/Documents/My Fruit Log.txt"

set FirstLineOfTxtFile to <this is where I need your help, Ask Different>


# Part 3
# Check to see if the first line of the .txt file is today's date.

set TodayDateAlreadyWritten to false

if FirstLineOfTxtFile contains FormattedTodayDate then
    set TodayDateAlreadyWritten to true
end if


# Part 4
# Write today's date to the first line of the .txt file (if necessary).

if TodayDateAlreadyWritten = false then

    set TextToWrite to FormattedTodayDate & "
    "       
    set OriginalText to quoted form of (do shell script "cat " & Target_Filepath)
    set TextToWrite to quoted form of TextToWrite & "\n" & OriginalText
    do shell script "echo " & TextToWrite & " > " & Target_Filepath

end if

It is Part 2 where I am in need of assistance.

I may have made some mistakes in any of the parts of the above code (but none to my knowledge), so please feel free to correct me as you see fit.

These are my sources:

Part 1: Formatting short dates in AppleScript

Part 4: How to prepend to text file in AppleScript?

1
  • I've update the answer to address the carriage return issue. Commented Nov 28, 2016 at 20:57

2 Answers 2

2

Okay, I believe I've narrowed down the 0D bug in relation to using cat in the do shell script command and have modified the code so it doesn't introduce carriage returns, at least so far in testing just this code presented below. I would have to do further testing to see explicitly where the bug is however I've recoded it to use a do shell script command in a manner to write to the file without introducing carriage returns.

However I've commented out the first rewriting of Part 4 that uses the do shell script command because while not introducing carriage returns it does add an empty line to the end of target file each time it's runs and while not fatal nonetheless I'm not sure you'd want it to happen. So, I've added an alternate way not using a do shell script command.

Note that I prefer to use the camelCase naming convention for my variables, so I've rewritten all of the code adding additional code and comments as I prefer them. Sorry if this inconveniences you however I needed to do it in a manner that enabled me to effectively work through any issues. Feel free to modify as needed/wanted.

The code below works on the target file whether or not it initially contains ASCII Text content and I've verified on my system after multiple writes there are no carriage returns introduced and the original target file was first verified, whether empty or not, had no carriage returns and no line feeds were converted at any time as compared to other versions of code that caused this issue.

--    # Part 1 - Get and format today's date.

set todaysDate to (current date)
set y to text -4 thru -1 of ("0000" & (year of todaysDate))
set m to text -2 thru -1 of ("00" & ((month of todaysDate) as integer))
set d to text -2 thru -1 of ("00" & (day of todaysDate))

set formattedTodaysDate to y & "_" & m & "_" & d & " -" as string


--    # Part 2 - Get the first line of the target file.

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

--    # Initialize firstLineOfFile variable in case the targetFilePathname file is empty.

set firstLineOfFile to ""
try
    --    # The commented line of code below is to be used when defining the actual code
    --    # in order to ensure a line feed "\n" is used and not a carriage return "\r".
    --    # Note that when compiled, the "\n" is converted to a literal newline
    --    # and a commented code line will be shown for all similiar instances.

    --    # set firstLineOfFile to first item of (read targetFilePathname using delimiter "\n")

    set firstLineOfFile to first item of (read targetFilePathname using delimiter "\n")
end try


--    # Part 3 - Check to see if the first line of the target file is today's date.

set isTodaysDateAlreadyWritten to false
if firstLineOfFile is equal to formattedTodaysDate then
    set isTodaysDateAlreadyWritten to true
end if


(*
--    # Part 4 - Write today's date to the first line of the target file, if necessary.

if isTodaysDateAlreadyWritten is equal to false then
    --    # set theTextToWrite to formattedTodaysDate & "\n"    
    set theTextToWrite to formattedTodaysDate & "\n"
    set theOriginalText to ""
    try
        set theOriginalText to (read targetFilePathname) as string
    end try
    --    # set theTextToWrite to theTextToWrite & "\n" & theOriginalText
    set theTextToWrite to theTextToWrite & "\n" & theOriginalText

    do shell script "echo " & quoted form of theTextToWrite & " > " & quoted form of targetFilePathname
end if
*)

--    # While the commented out Part 4 above does work by not introducing any carriage returns nonetheless
--    # it does introduce and additional empty line at the end of the target file and therefore will not be used.
--    #
--    # The following Part 4 does not use the do shell script command to make the writes nor does it add extra lines.


--    # Part 4 - Write today's date to the first line of the target file, if necessary.

if isTodaysDateAlreadyWritten is equal to false then
    --    # set theTextToWrite to formattedTodaysDate & "\n"    
    set theTextToWrite to formattedTodaysDate & "\n"
    set theOriginalText to ""
    try
        set theOriginalText to (read targetFilePathname) as string
    end try
    --    # set theTextToWrite to theTextToWrite & "\n" & theOriginalText
    set theTextToWrite to theTextToWrite & "\n" & theOriginalText
    try
        set referenceNumber to open for access targetFilePathname with write permission
        write theTextToWrite 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
end if
8
  • When I run your script, copied verbatim, I am presented with an error message stating, "File I/O Error... File file My Fruit Log.txt is already open. number -49". This is despite the fact that the file is not open (and nor is TextEdit even running) when I run the script. I can't figure out why this error is being triggered. Even if the .txt file was open while I ran the script (which it is not), why should that prevent the script from reading and writing to the file? Commented Nov 29, 2016 at 2:46
  • Okay, this is very strange. When I run the script from a system-wide Service (by clicking on the Service title under the Services menu found if you click on the current application title in the top-left corner of the screen), and even if the .txt file really is open when I run the Service, it runs successfully without error. But when I run the code from within Automator (by clicking the play-button-triangle labeled "Run" in the top-right corner of the screen), I am always presented with this error. Commented Nov 29, 2016 at 2:58
  • @rubik's sphere, This is a prime reason why proper and adequate error handling must be used. You may not think the file is open however if you get that error it's open! BTW open in this instance does does not mean it's visible or minimized, it means there a file handle open for that file. This means that open for access occurred on the file but was not closed by close access .... Meaning that before you ran my new code you must have ran open for access and the file handle (referenceNumber) was never closed. Maybe from the other code in the other question. I know my present code is solid! Commented Nov 29, 2016 at 3:26
  • @rubik's sphere, I've copied this code directly out of my own answer and with or without the existence of the target file it works as coded and without any issue when run from Script Editor. I can add + 86400 * 2 to the set todaysDate to (current date) line and increment the multiplier after the * each time I run it and it adds the next days date to the file as it's supposed to. You'll need to close the file handle to continue with the target filename or change the filename a bit for testing till you close the file handle on that named file. Commented Nov 29, 2016 at 3:27
  • @rubik's sphere, I tested this in Script Editor and Automator under OS X 10.11.6 and it just works! Even if I'm going to use AppleScript code in Automator I always write and test it under Script Editor first then copy it to Automator and only a few times have I had to modify the code in Automator other then what's expected to handle the overall workflow. Commented Nov 29, 2016 at 3:27
0

Hello, for your part 2, a script shell script "head -n 1" will allow you to assign the value (text) of line 1 of your file to your variable FirstLineOfTxtFile and then to format your text like you Wish.

set TodayDate to current date
set y to text -4 thru -1 of ("0000" & (year of TodayDate))
set m to text -2 thru -1 of ("00" & ((month of TodayDate) as integer))
set d to text -2 thru -1 of ("00" & (day of TodayDate))
set FormattedTodayDate to y & "_" & m & "_" & d & " -"

set Target_Filepath to quoted form of ""/Users/Me/Desktop/Documents/My Fruit Log.txt""

set FirstLineOfTxtFile to do shell script "head -n 1 '"/Users/Me/Desktop/Documents/My Fruit Log.txt"'"
set TodayDateAlreadyWritten to false

if FirstLineOfTxtFile contains FormattedTodayDate then
    set TodayDateAlreadyWritten to true
end if


# Part 4
# Write today's date to the first line of the .txt file (if necessary).

if TodayDateAlreadyWritten = false then

    set TextToWrite to FormattedTodayDate & "
    "
    set OriginalText to quoted form of (do shell script "cat " & Target_Filepath)
    set TextToWrite to quoted form of TextToWrite & "
" & OriginalText
    do shell script "echo " & TextToWrite & " > " & Target_Filepath

end if
2
  • Since the code you've provided won't compile as it has errors, I can only assume you didn't actually test it before posting it! Commented Dec 14, 2016 at 4:05
  • @user3439894 Can I encourage you to either edit the post or use a comment to be more specific about these errors?
    – nohillside
    Commented Jan 22, 2019 at 16:11

You must log in to answer this question.

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