The following script will add/write text to the end of a text file. However, I need a script that will add/write to the beginning of a text file. I realize I could read the data to a variable and then add to the beginning of this variable and then write back to the file but I am trying to avoid this solution because some of the text files that I am using are very large.
Any information would be greatly appreciated,
CarbonQuark
set fileRef to open for access alias "Macintosh HD:test.txt" with write permission
write "Hello World" to fileRef starting at EOF
close access fileRef
I don’t think there’s any way to push down the content of a file so something can be prepended. I’m afraid you’re stuck with reading, adding the piece in front, and writing it back or creating a new file with your prepended stuff and writing the old file to the end of it.
Thanks for the info! That was what I was afraid of. Some of the text files I have are bigger than 20 megs and crash the script. I was hoping this could be accomplished with applescript / shell scripting.
You might try this to deal with prepending to large files:
property blockSize : 4096
on run
local origFile
set origFile to (choose file default location path to temporary items)
prependData to origFile from ¬
"This is the new start of the file! (new blank line for free, too)" & (ASCII character 10) & (ASCII character 10) ¬
without deletingOldFile
end run
to prependData to origFile from theNewData given deletingOldFile:deletingOldFile
local origFileName, oldFileName, newFilePath
tell application "Finder"
-- This could be better about choosing file names.
local folderPath, newFileName, oldFilePath
set origFileName to name of origFile
set folderPath to container of origFile as string
set newFileName to "new " & origFileName
set oldFileName to "old " & origFileName
set newFilePath to folderPath & newFileName
set oldFilePath to folderPath & oldFileName
if exists newFilePath then error "new file already exists: " & newFilePath
if not deletingOldFile and ¬
(exists oldFilePath) then error "old file already exists: " & oldFilePath
end tell
local writeFile, readFile
try
set writeFile to open for access newFilePath with write permission
set readFile to open for access origFile without write permission
set eof writeFile to 0
write theNewData to writeFile
local gotReadError, theData
set gotReadError to false
repeat until gotReadError
try
set theData to (read readFile for blockSize as data)
on error
set gotReadError to true
end try
if not gotReadError then write theData to writeFile
end repeat
close access writeFile
set writeFile to missing value
close access readFile
set readFile to missing value
on error m
if writeFile is not missing value then close access writeFile
if readFile is not missing value then close access readFile
display dialog m
end try
tell application "Finder"
if deletingOldFile then
delete origFile
else
-- This may fail if a file with this name snuck in while we were copying data.
set name of origFile to oldFileName
end if
set name of item newFilePath to origFileName
end tell
end prependData
I only tested it with small files (and even smaller blocks, to make sure the looping works).
You probably want to make up your own old file handling and naming stuff. And, as always, be sure you have backups of your files before you attempt any potentially dangerous operations on them (like rewriting them from scratch!). If it turns out to be too slow on your 20MB files, try a larger block size.
Model: iBook G4 933
AppleScript: 1.10.7
Browser: Safari 419.3
Operating System: Mac OS X (10.4)
Edit history: deleted a stale comment and an old log statement from the script text, rearranged local variable delarations, rewrote with label parameter in handler definition to use given (per Nigel Garvey)
You should only use ‘with’ or ‘without’ in the call to the handler. The correct syntax for the first line in the handler statement itself (since you’re also using ‘deletingOldFile’ within the handler) is:
to prependData to origFile from theNewData given deletingOldFile:deletingOldFile
Otherwise, the script appears to work very well.
Just as a proof of concept, I couldn’t resist doing a version that actually writes the new data to the beginning of the original file, moving the remaining data upfile with a rolling read/write alternation that uses two concurrently open accesses to it. I don’t recommend doing it this way though (except with a duplicate file) as any errors during the process will leave the file in a partially overwritten state!
property blockSize : 4096 -- Must be more than the length of the prepended data.
on run
local origFile
set origFile to (choose file)
prependData to origFile from ¬
"This is the new start of the file! (new blank line for free, too)" & (ASCII character 10) & (ASCII character 10)
end run
to prependData to origFile from theNewData
-- Open two accesses to the file, one with write permission.
set readRef to (open for access origFile)
try
set writeRef to (open for access origFile with write permission)
try
set origLength to (get eof readRef)
set loopCount to origLength div blockSize
set theOddBits to origLength mod blockSize
-- The first data to be written will be the new stuff.
set writeBlock to theNewData
repeat loopCount times
-- Read a block's worth of data from the file.
set readBlock to (read readRef for blockSize as data)
-- Partially overwrite it in the file with the stuff to be written.
write writeBlock to writeRef
-- Prepare to write the just-read stuff after the next read.
set writeBlock to readBlock
end repeat
-- Read the remaining, less-than-blockSize data, if any.
if (theOddBits > 0) then
set readBlock to (read readRef for theOddBits as data)
write writeBlock to writeRef
set writeBlock to readBlock
end if
-- Write whatever's left to the file.
write writeBlock to writeRef
on error msg
display dialog msg buttons {"OK"} default button 1 with icon stop
end try
close access writeRef
on error msg
display dialog msg buttons {"OK"} default button 1 with icon stop
end try
close access readRef
end prependData