Applescript to insert comma at end of (some) lines in TextWrangler

Hi everyone,

I’m running an exiftool command in Terminal to generate a list of photoshop files with all their respective layer names.

The data that is returned gets dumped into a text document on my Desktop but I need to process this text a little further so that eventually I can paste a simple string of filenames, separated by commas, into Lightroom when I perform a search for filenames.

So far I have been running multiple find/replace searches in TextWrangler to clean up the text for my needs then I found out that I could consolidate several individual searches into a single AppleScript and be done with one click.

In that regard this is really more of a TextWrangler, grep question than it is an AppleScript question, but I know this a solid pool of knowledge and someone here problems knows this answer.

Currently, when I run my AppleScript I’m left with multiple lines of filenames. Most of those lines have commas as the end, which I want to keep. But for the few lines that do not end with commas, how can I do a replacement that is essentially: “for any lines that do not end with a comma — insert a comma”?

As an example, let’s say I’m left with a text doc that looks like this:

854A9142,854A9144,854A9143,854A9142
854A9589,
854A9607,
854A9850,
854A9851,
854A9852,
854A9854,
EE8A8457,EE8A8466,EE8A8464,EE8A8462,EE8A8459,EE8A8457
EE8A8760,
EE8A8764,
EE8A8769,
EE8A8774,
EE8A8775,
EE8A8776,
EE8A8842,EE8A8861,EE8A8859,EE8A8857,EE8A8855,EE8A8852,EE8A8850,EE8A8848,EE8A8842

…those three long lines do not have commas at the end and ultimately everything needs to be comma separated. So my original goal was to simply add commas to the end of any lines that don’t have one then removing the line breaks.

I should add that I already have a “workaround” that may be satisfactory. I can do a find/replace for all line breaks, replacing the breaks with commas. Then I end up with several sets of double commas, but one more search for , replacing with , fixes that. Perhaps this is a viable solution.

However, even if this last little “trick” works I’m still left with a single comma at the very beginning of the string. In TextWrangler I can remove that comma with a search for ^. replacing with nothing.

But…I can’t get that same grep command to run in AppleScript. I realize I need to insert \ to get grep commands to work in AppleScript but evidently I can’t get the correct syntax in AppleScript to remove that very first character, a comma.

This workaround changes the subject line of my post. I suppose it’s either: how to insert a comma at the end of lines without one? Or…how do I remove the very first character of a line in TextWrangler, using AppleScript / grep syntax?

Thanks in advance!

[edited to add:] I should probably add a snippet of my AppleScript so far. This one gets around the problem with the missing commas at the ends of some lines by doing my trick: "replace line breaks with comma’ then “replace , with ,” but if this is going to be my solution I would still like to remove that initial character, a comma, from the resulting string. (There are folder paths, specific to my system, that I’ve “redacted” here.)

tell application "TextWrangler"
	set s_options to {starting at top:true}
	replace "SourceFile,LayerNames" using "" searching in text 1 of active document of text window 1 options s_options
	replace "***[folder path 1]***" using "" searching in text 1 of active document of text window 1 options s_options
	replace "***[folder path 2]***" using "" searching in text 1 of active document of text window 1 options s_options
	replace "Background, Background copy" using "" searching in text 1 of active document of text window 1 options s_options
	replace ", Layer 1" using "" searching in text 1 of active document of text window 1 options s_options
	replace ".psd" using "" searching in text 1 of active document of text window 1 options s_options
	replace ".CR3" using "" searching in text 1 of active document of text window 1 options s_options
	replace "\"" using "" searching in text 1 of active document of text window 1 options s_options
	replace "\\r" using "," searching in text 1 of active document of text window 1 options s_options
	replace ",," using "," searching in text 1 of active document of text window 1 options s_options
	replace " " using "" searching in text 1 of active document of text window 1 options s_options
end tell

Hi.

A grep solution to the comma problem would be to replace every line break not preceded by a comma with a comma and then delete all the remaining line breaks

tell application "TextWrangler"
	tell text of document 1
		replace "(?<!,)\\r" using "," options {search mode:grep, starting at top:true}
		replace "\\r" using "" options {starting at top:true}
	end tell
end tell

Looking at your script, it may be possible to write a single regex pattern to cover most of the deletions, but I wouldn’t like to offer this without knowing exactly what’s in the text. In any case, it’s easier to edit the script in its current form should you need to do so later.

Editing text files can be done in AppleScript without using an application like TextWrangler at all. But at least this way you can see the results before saving.

Nigel’s suggetion does exactly what the OP wants, but I thought I’d give this a try with basic AppleScript. I first wrote this using text item delimiters, but the following is more reliable in handling different line endings and blank paragraphs.

set theText to "854A9142,854A9144,854A9143,854A9142
854A9142,854A9144,854A9143,854A9142,

854A9589
854A9142,"

set theCSV to getCSV(theText)

on getCSV(theText)
	set theText to paragraphs of theText
	repeat with i from 1 to (length of theText)
		if item i of theText is equal to "" then
			set item i of theText to missing value
		else if item i of theText does not end with "," then
			set item i of theText to item i of theText & ","
		end if
	end repeat
	set {TID, text item delimiters} to {text item delimiters, ""}
	set theText to (text of theText) as text
	set text item delimiters to TID
	return text 1 thru -2 of theText
end getCSV

Hi. The question was adequately answered as asked by Nigel, however, lookbacks require PCRE—rather than extended regex—so that pattern may not work everywhere; I don’t know if ASObj-C is set up for PCRE or not… perhaps Shane or another poster more familiar with that method may chime in? As the OP is already doing things with the Terminal, this is another way it might be done without the TextWrangler dependency in the shell.

This translates to: except for lines not ending with a comma, replace everything with itself and append a comma:

do shell script "awk '/[^,]$/{sub(/.*/,$1\",\")}; 1'  " & my (choose file)'s POSIX path's quoted form & " | xargs" 

ASObjC uses the ICU regex engine, which does indeed support lookbacks.

Hi everyone,

Thanks for the input so far. Sorry it’s taken a while to return to this thread. I’ve been super-busy recently. But I didn’t want too much time to pass before coming back to update you with my progress (and a few changes.)

For the sake of thoroughness I’ll outline the entire process as it stands now.

The terminal code I’ve been running, that generates this list/document looks like this:

exiftool -csv -r -ext .psd -LayerNames [path to folder] > [file destination] /list_of_layers.csv

This is what I’ve been using to generate the csv file that I open and manipulate in TextWrangler via AppleScript. Typical output will look something like this. (I’m redacting actual file paths here.)

SourceFile,LayerNames
[path to folder 1]854A9142.psd,“854A9144.CR3, 854A9143.CR3, 854A9142.CR3”
[path to folder 1]854A9589.psd,“Background, Background copy”
[path to folder 1]854A9607.psd,“Background, Background copy”
[path to folder 1]854A9850.psd,“Background, Background copy”
[path to folder 1]854A9851.psd,“Background, Background copy, Layer 1”
[path to folder 1]854A9852.psd,“Background, Background copy”
[path to folder 1]854A9854.psd,“Background, Background copy”
[path to folder 2]EE8A8457.psd,“EE8A8466.CR3, EE8A8464.CR3, EE8A8462.CR3, EE8A8459.CR3, EE8A8457.CR3, Layer 1”
[path to folder 2]EE8A8760.psd,“Background, Background copy”
[path to folder 2]EE8A8764.psd,“Background, Background copy”
[path to folder 2]EE8A8769.psd,“Background, Background copy”
[path to folder 2]EE8A8774.psd,“Background, Background copy”
[path to folder 2]EE8A8775.psd,“Background, Background copy”
[path to folder 2]EE8A8776.psd,“Background, Background copy”
[path to folder 2]EE8A8842.psd,“EE8A8861.CR3, EE8A8859.CR3, EE8A8857.CR3, EE8A8855.CR3, EE8A8852.CR3, EE8A8850.CR3, EE8A8848.CR3, EE8A8842.CR3, Layer 1”

My AppleScript has two lines that delete the file paths from the list. Since these file paths will be different each time I have ‘dummy’ text in the script where I’ll paste in the proper path before running the script. The script looks like this, again with file paths redacted already:

tell application "TextWrangler"
	set s_options to {starting at top:true}
	repeat with i in (get every text document)
		delete text of i's (lines 1 thru 1)
	end repeat
	replace "[path to folder 1]" using "" searching in text 1 of active document of text window 1 options s_options
	replace "[path to folder 2]" using "" searching in text 1 of active document of text window 1 options s_options
	replace "Background, Background copy" using "" searching in text 1 of active document of text window 1 options s_options
	replace ", Layer 1" using "" searching in text 1 of active document of text window 1 options s_options
	replace ", Layer 2" using "" searching in text 1 of active document of text window 1 options s_options
	replace " copy" using "" searching in text 1 of active document of text window 1 options s_options
	replace ".psd" using "" searching in text 1 of active document of text window 1 options s_options
	replace ".CR2" using "" searching in text 1 of active document of text window 1 options s_options
	replace ".CR3" using "" searching in text 1 of active document of text window 1 options s_options
	replace "\"" using "" searching in text 1 of active document of text window 1 options s_options
	replace "\\r" using "," searching in text 1 of active document of text window 1 options s_options
	replace ",," using "," searching in text 1 of active document of text window 1 options s_options
	replace " " using "" searching in text 1 of active document of text window 1 options s_options
end tell

That first little loop is surely overkill. I found it elsewhere as a mechanism to “delete lines 1 thru X” but I only need to eliminate the very first line so I modified it to delete “lines 1 thru 1”. Again, I’m sure there’s a more efficient way to do that, but this is what I’m using as of now.

I arrived at this point right around the time that I started this thread. But I’ve tweaked the first procedure, getting my respective .csv file, using Automator so there are some additional processes I’ve combined into the first move. In Automator:

  1. Ask for Finder Items (the main folder to scan for PSD files, there will be a couple of subfolders here where the PSDs actually reside.)
  2. Set Value of Variable (main folder location)
  3. Run Shell Script (exiftool command which saves the .csv file in the main folder that is being scanned)
  4. Get Value of Variable (main folder location)
  5. Open Finder Items (main folder location)
  6. Run Shell Script (opens the .csv file in TextWrangler)

There will always be a tiny bit of fiddling each time I run the entire process, to make it work for those subfolders where the images live, but otherwise there are only two major steps:

• Run the Automator (app) to get the main folder, save .csv file here, open the folder location, open the .csv file

• Run the AppleScript, but only after I’ve pasted in the subfolder paths where the PSDs reside.

As always, I’m sure there could be some tidying up in the AppleScript. “searching in text 1 of active document of text window 1 options s_options” in every line seems redundant. There’s probably a way to make that more efficient. Then using the repeat loop when I only need to delete the first line every time is likely overkill as well.

Overall though I’m pretty happy with where it’s ended up. Any further input is always welcome.

Thanks again!

Just a handful of comments on using Textwrangler in this manner:

If you add ‘search mode:grep’ as an option, then you can use grep syntax.
[format]set s_options to {starting at top:true, search mode:grep}[/format]

Textwrangler (I’m pretty sure) and BBEdit offer recordability, so clicking the ‘record’ button in script editor prior to searching for text in the editor will create the appropriate code. You may need to tweak that code, of course. This can be especially helpful when trying to figure out how many backslashes you need to ensure that everything is escaped properly.

You could probably set a variable to the redundant search text and then search in that. At the very least, it would shorten all the lines.
[format]set t1 to text 1 of active document of text window 1[/format]

Some specifics: You could probably replace all of your file extension searches with a single generalized one (assuming that your data doesn’t have oddball stuff in it) — see below. The ‘\w+\d?’ searches for one or more letters, optionally followed by a single digit.

Process lines containing allows you to quickly remove lines that contain offending text (among other things).

tell application "BBEdit"
	activate
	replace "\\.\\w+\\d?" using "" searching in text 1 of text document 1 options {search mode:grep, starting at top:true}
	replace ",\\ ?" using ",\\r" searching in text 1 of text document 1 options {search mode:grep, starting at top:true}
	replace "^\"" using "" searching in text 1 of text document 1 options {search mode:grep, starting at top:true}
	replace "\"$" using "," searching in text 1 of text document 1 options {search mode:grep, starting at top:true}
	
	process lines containing text 1 of text document 1 matching string "Background" output options {deleting matched lines:true}
	process lines containing text 1 of text document 1 matching string "Layer" output options {deleting matched lines:true}
end tell

Finally, Bare Bones killed off textwrangler a few years ago and now has a free mode for bbedit that serves as a replacement for TW. You might find it worth looking into.

Browser: Firefox 101.0
Operating System: macOS 10.12