Edit many files with TextWrangler

Hi, I want to edit many nfo files with TextWrangler.
Every nfo file is inside its folder.

My files are like these one:

Desired result:

I am very new to AppleScript. Searching the forum and looking for part of codes I could arrange the next script but nothing happens.


set theSourceFolder to (choose folder with prompt "Select a folder:")

-- Select only all the nfo files of all subfolders
tell application "Finder"
	set filesArray to every file of theSourceFolder whose name extension is "nfo"
end tell

repeat with aFile in filesArray
	
	tell application "TextWrangler"
		open (aFile as alias)
		tell document 1
			-- Copy to the clipboard the matched lines and paste them into the document
			process lines containing matching string "(<\\?xml|<movie>|</movie>|</id>|</title>|<actor>|</actor>|</name>|</genre>|</year>|</tag>|</set>|</plot>)" matching with grep true ¬
				output options {copying to clipboard:true}
			select text 1 of project window 1
			paste
			-- Replace the title with the id data and save the document as nfo file			
			replace "<title>([\\w\\W]+)\\s-\\s([\\w\\W]+)<\\/title>" using "<title>\\1<\\/title>" searching in text 1 options {search mode:grep, starting at top:true, match words:true}
			save
		end tell
	end tell
	-- Clear and empty contents in the clipboard	
	tell application "System Events"
		try
			set the clipboard to ""
		on error err_message
			display dialog err_message
		end try
	end tell
	
end repeat

Apreciate if someone could help me to find my errors and make the script work.

Thank you in advance,
Alejandro

Model: mac mini 2011
AppleScript: 2.6.1
Browser: Safari 537.36
Operating System: Mac OS X (10.9)

Hi Alejandro. Welcome to MacScripter.

It’s not really necessary to use TextWrangler to edit the files, but to get your script working:

set theSourceFolder to (choose folder with prompt "Select a folder:")

-- Select only the nfo files of the folder.
tell application "Finder"
	set filesArray to (every file of theSourceFolder whose name ends with ".nfo") as alias list -- The Finder doesn't recognise "nfo" as a file extension on my machine.  :\
end tell

repeat with aFile in filesArray
	
	tell application "TextWrangler"
		set docName to name of (open aFile)
		tell document docName
			-- Set the document text to just the lines which need to be kept.
			set its text to copied lines of (process lines containing matching string "(<\\?xml|<movie>|</movie>|</id>|</title>|<actor>|</actor>|</name>|</genre>|</year>|</tag>|</set>|</plot>)" with matching with grep)
			-- Find the id text.
			set idText to found text of (find "(?<=<id>)[^<]*+(?=</id>)" options {search mode:grep, starting at top:true})
			-- Replace the title with the id text.
			replace "(?<=<title>)[^<]*+(?=</title>)" using idText options {search mode:grep, starting at top:true}
			close saving yes
		end tell
	end tell
end repeat

Nigel,

Thank you so much for your very kind help.

The script works but only for the first nfo file. Then I get the next error: “TextWrangler has detected an error: Cannot get the name of text document 1”

Also, when I run the script in my “Films” folder nothing happens.
My folder structure is like this:

You said that is not necessary TextWrangler to edit the files. Is there any other way?

I was trying to add this extra line “FAVORITES” before the last line of my edited files.
I don`t have any idea how to make it. Sorry for not mention it before.

Thank you for any help. I will still crashing my head how to solve this.

Alejandro

Ah. I suspect this is due to the potential problem I was actually trying to avoid by getting the document’s name! It worked well with a folder-full of files on my computer, but obviously the timing’s different on yours.

In the script you posted, there’s a contraction between the comment (‘files of all subfolders’) and the code (‘every file of theSourceFolder’). I made the wrong guess about which was intended.

Here’s another version which hopefully addresses the problems and inserts the additional line you wanted. The added line is indented with two spaces as that’s how it comes off this forum page, but a tab can easily be used instead if the lines in the files are tab-indented.

set theSourceFolder to (choose folder with prompt "Select a folder:")

-- Select all the nfo files in the folder hierarchy.
tell application "Finder"
	set filesArray to (every file of entire contents of theSourceFolder whose name ends with ".nfo") as alias list -- The Finder doesn't recognise "nfo" as a file extension on my machine.  :\
end tell

tell application "TextWrangler"
	activate
	repeat with aFile in filesArray
		set docName to name of (open aFile)
		tell document docName
			-- Set the document text to just the lines which need to be kept.
			set its text to copied lines of (process lines containing matching string "(<\\?xml|<movie>|</movie>|</id>|</title>|<actor>|</actor>|</name>|</genre>|</year>|</tag>|</set>|</plot>)" with matching with grep)
			-- Find the id text.
			set idText to found text of (find "(?<=<id>)[^<]*+(?=</id>)" options {search mode:grep, starting at top:true})
			-- Replace the title with the id text.
			replace "(?<=<title>)[^<]*+(?=</title>)" using idText options {search mode:grep, starting at top:true}
			-- Replace the "</movie>" line with another line and it.
			replace "</movie>" using "  <genre>FAVORITES</genre>" & linefeed & "</movie>" options {wrap around:true}
			-- Save and close the document.
			close saving yes
			-- Ensure the document's gone before opening another.
			repeat while (it exists)
				delay 0.2
			end repeat
		end tell
	end repeat
end tell

There are various ways in which a script can edit the text of a file without having to open it in an application’s visible document. I’ll see if I can put an example together this afternoon. To judge from TextWrangler’s scripting dictionary, it can itself edit batches of files in situ, but I can’t see how to script that. :confused:

That’s it!
Now, the script runs flawlessly.

Thank you so much, Nigel.
You saved me hours of work.

Thank you so much, again

Here’s a “vanilla” version, which is more code, but faster. Like the TextWrangler script, it assumes that the text between the tags doesn’t include any linefeeds or returns.

set theSourceFolder to (choose folder with prompt "Select a folder:")

-- Select all the nfo files in the folder hierarchy.
tell application "Finder"
	set filesArray to (every file of entire contents of theSourceFolder whose name ends with ".nfo") as alias list -- The Finder doesn't recognise "nfo" as a file extension on my machine.  :\
end tell

set requiredKeys to {"movie", "movie", "id", "title", "actor", "name", "genre", "year", "tag", "set", "plot"}
set astid to AppleScript's text item delimiters
repeat with aFile in filesArray
	-- Open an access channel to this file.
	set fRef to (open for access aFile with write permission)
	try
		-- Read the file, assuming its contents to be UTF-8 text, and get a list of the lines.
		set textLines to paragraphs of (read fRef as «class utf8»)
		-- Set AppleScripts text item delimiters to the XML tag delimiters.
		set AppleScript's text item delimiters to {"</", "<", ">"}
		-- Treat each line according to the contents of its first tag label.
		repeat with i from 1 to (count textLines)
			set thisLine to item i of textLines
			set tagLabel to text item 2 of thisLine
			if (tagLabel is "title") then
				-- Note the title line number.
				set titleLineIndex to i
			else if (tagLabel is "id") then
				-- Note the ID value.
				set theID to text item 3 of thisLine
			else if (thisLine contains "</movie>") then
				-- Insert an extra "<genre>" line before the "</movie>" one.
				set item i of textLines to ("  <genre>FAVORITES</genre>" & linefeed & thisLine)
			else if not ((tagLabel is in requiredKeys) or (tagLabel begins with "?xml")) then
				-- Zap any unwanted line.
				set item i of textLines to missing value
			end if
		end repeat
		-- Replace the title in the title line with the ID value.
		set oldTitleLine to item titleLineIndex of textLines
		set newTitleline to text 1 thru text item 2 of oldTitleLine & ">" & theID & "<" & text from text item 4 to -1 of oldTitleLine
		set item titleLineIndex of textLines to newTitleline
		-- Reunite the unzapped lines as a single text.
		set AppleScript's text item delimiters to linefeed
		set editedText to (textLines's text) as text
		-- Write this text back to the file.
		set eof fRef to 0
		write editedText as «class utf8» to fRef
		-- Close the access channel.
		close access fRef
	on error errMsg
		-- If there's an error, close the file and explain the problem.
		close access fRef
		set AppleScript's text item delimiters to astid
		display dialog errMsg
	end try
end repeat
set AppleScript's text item delimiters to astid

Nigel, as you said, your last code is faster.

Thank you very much for your help and time.