Copy link to clipboard
Copied
Hi there,
Let us say I have six Photoshop files: 1.psd, 2.psd, ..., 6.psd. All of these files contain the word “LoremIpsum” in random text layers, within each document. Is there a way I can search for “LoremIpsum” in all documents and replace it with “Dolor Sit Amet”, all in one go? This is just an example, I need to replace various words, not just one.
I have tried "batch find and replace" software (including powerful tools like Power Grep) but they do not work with psd files… Is there a javascript of external plugin for this kind of task?
Thanks!
Copy link to clipboard
Copied
I would have made the text file a two line file. The first line would be for the search terms and the second for the replacement terms.
'Sun','Day','Hot'
'Moon','Night','Cold'
Then I would replace these lines
var theTexts = readPref ("….txt", false);
var theArray1 = theTexts.slice(0, Math.round(theTexts.length/2));
var theArray2 = theTexts.slice(Math.round(theTexts.length/2), theTexts.length);
with these
var theTexts = readPref ("...filePath or file object");
var theArray1 = theTexts[0];
var theArray2 = theTexts.[1];
and replaced the readPerf function with this
////// read prefs file //////
function readPref (thePath) {
if (File(thePath).exists == true) {
var file = File(thePath);
file.open("r");
var textArray = [];
textArray.push(file.readln().split(","));// make array of search terms
textArray.push(file.readln().split(","));// make array of replace terms
file.close();
return textArray;
}
};
Ideally it would have checks to make sure there are two lines and the number of terms match.
Copy link to clipboard
Copied
Thank you! For me (Photoshop CS3), the updated script gives an error:
Error 1243: Illegal argument - Argument 2
-Required value is missing
Line: 41
-> desc23.putString(idreplace, replaceWith);
Copy link to clipboard
Copied
My bad, it works.... Results are identical with previous version.
Copy link to clipboard
Copied
Yes, I expected the results would be the same. I just thought that having a two line text file with one line for the search terms and the second for the replacement terms was better than a one line text file. I think the two line text file is better because you don't have to count the terms to determine which is a search term and which is a replacement term.
Copy link to clipboard
Copied
You are right, Mike, your approach offers advantages indeed.
Setting up the file should be much more convenient thus.
Copy link to clipboard
Copied
Thank you both very much, it has been a pleasure! I already started using the original script by c.pfaffenbichler, with additions by Michael L Hale
Hope this thread will be of help to other people, in the future.
Over and out
Copy link to clipboard
Copied
Me again
The script does a great job at replacing a word with another word. But how should I approach replacing a word with a few paragraphs of text? It works, but when it encounters a space betwen paragraphs (a blank line, like the one below) it stops.
I have tried using \n (as I use in Javascript alerts) but it does not work... Is there another way?
Thank you!!
Copy link to clipboard
Copied
Could you post the Script and the txt-file you work with now?
Copy link to clipboard
Copied
SCRIPT:
#target photoshop
if (app.documents.length > 0) {
for (var n = 0; n < app.documents.length; n++) {
app.activeDocument = app.documents
app.activeDocument.suspendHistory("replace text", "main()")
}
};
function main () {
var myDocument = app.activeDocument;
var theTexts = readPref ("D:/Directory/text-file.txt");
var theArray1 = theTexts[0];
var theArray2 = theTexts[1];
for (var b = 0; b < theArray1.length; b++) {
replaceText (theArray1, theArray2)
};
};
function replaceText (replaceThis, replaceWith) {
var idreplace = stringIDToTypeID( "replace" );
var desc22 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref3 = new ActionReference();
var idPrpr = charIDToTypeID( "Prpr" );
var idreplace = stringIDToTypeID( "replace" );
ref3.putProperty( idPrpr, idreplace );
var idTxLr = charIDToTypeID( "TxLr" );
var idOrdn = charIDToTypeID( "Ordn" );
var idAl = charIDToTypeID( "Al " );
ref3.putEnumerated( idTxLr, idOrdn, idAl );
desc22.putReference( idnull, ref3 );
var idUsng = charIDToTypeID( "Usng" );
var desc23 = new ActionDescriptor();
var idfind = stringIDToTypeID( "find" );
desc23.putString( idfind, replaceThis );
var idreplace = stringIDToTypeID( "replace" );
desc23.putString( idreplace, replaceWith );
var idcheckAll = stringIDToTypeID( "checkAll" );
desc23.putBoolean( idcheckAll, true );
var idFwd = charIDToTypeID( "Fwd " );
desc23.putBoolean( idFwd, false );
var idcaseSensitive = stringIDToTypeID( "caseSensitive" );
desc23.putBoolean( idcaseSensitive, true );
var idwholeWord = stringIDToTypeID( "wholeWord" );
desc23.putBoolean( idwholeWord, false );
var idignoreAccents = stringIDToTypeID( "ignoreAccents" );
desc23.putBoolean( idignoreAccents, false );
var idfindReplace = stringIDToTypeID( "findReplace" );
desc22.putObject( idUsng, idfindReplace, desc23 );
executeAction( idreplace, desc22, DialogModes.NO );
};
function readPref (thePath) {
if (File(thePath).exists == true) {
var file = File(thePath);
file.open("r");
var textArray = [];
textArray.push(file.readln().split("|"));
textArray.push(file.readln().split("|"));
file.close();
return textArray;
}
};
TEXT FILE:
Sun|Night|Cold
Moon|Day|Hot
Copy link to clipboard
Copied
First off, this would be super useful if I can get it working, so thanks so much in advance.
Just tried running the above script posted by Apod42... But it returned this error. Any ideas?
I'm running Photoshop CC.
----
- The object “in contents of all text layer” is not currently available.
Line: 48
-> executeAction( idreplace, desc22, DialogModes.NO );
----
Many thanks!
Copy link to clipboard
Copied
One could always foresake the readln in readPref and use some other letter/s to split the string in the txt-file into two. One would have to restructure the txt-file accordingly.
Copy link to clipboard
Copied
Hello,
Your last replay was for me or jdubbb? Show I work on this part:
textArray.push(file.readln().split("|"));
textArray.push(file.readln().split("|"));
Get rid of the readln?
As before, thank you!
Copy link to clipboard
Copied
I’m off for the weekend, so unless someone else provides a solution in the meantime I’ll try to get back to you in a couple of days.
Copy link to clipboard
Copied
Just got it working!
I made sure that I had just one of the target text layers selected in the layers panel.
Thank you so much. Saved me SO much time.
Copy link to clipboard
Copied
I am getting close to the desired result. The script below searches a Photoshop document for the word "Hello" and replaces this word with all the text inside an external .txt file. The only problem: it completely ignores paragraph breaks. I just cannot get this to work.
I understand that because the script uses Photoshop's built-in search/replace functions, it may have limitations. Nevertheless, is there any way to get the paragraph lines from the external file?
var file = new File ( "C:\\the-text-file.txt" );
file.open("r");
var str = file.read();
var id3 = stringIDToTypeID( "replace" );
var desc2 = new ActionDescriptor();
var id4 = charIDToTypeID( "null" );
var ref1 = new ActionReference();
var id5 = charIDToTypeID( "Prpr" );
var id6 = stringIDToTypeID( "replace" );
ref1.putProperty( id5, id6 );
var id7 = charIDToTypeID( "TxLr" );
var id8 = charIDToTypeID( "Ordn" );
var id9 = charIDToTypeID( "Al " );
ref1.putEnumerated( id7, id8, id9 );
desc2.putReference( id4, ref1 );
var id10 = charIDToTypeID( "Usng" );
var desc3 = new ActionDescriptor();
var id11 = stringIDToTypeID( "find" );
desc3.putString( id11, "Hello" );
var id12 = stringIDToTypeID( "replace" );
desc3.putString( id12, str );
var id13 = stringIDToTypeID( "checkAll" );
desc3.putBoolean( id13, true );
var id14 = charIDToTypeID( "Fwd " );
desc3.putBoolean( id14, false );
var id15 = stringIDToTypeID( "caseSensitive" );
desc3.putBoolean( id15, true );
var id16 = stringIDToTypeID( "wholeWord" );
desc3.putBoolean( id16, false );
var id17 = stringIDToTypeID( "findReplace" );
desc2.putObject( id10, id17, desc3 );
executeAction( id3, desc2, DialogModes.NO );
Copy link to clipboard
Copied
After some research I found this snippet of code, I think it's similar to what I need; I just don’t have the expertise to implement it. The code I need should ideally add a paragraph break when it encounters \n or \r in the external text file...
var text = Stdlib.readFromFile(sFile);
lyr.textItem.contents = text.replace(/\n/g, '\r');
Copy link to clipboard
Copied
Please try this.
// replace text elements in type layers;
// 2014, use it at your own risk;
#target photoshop
if (app.documents.length > 0) {
for (var n = 0; n < app.documents.length; n++) {
app.activeDocument = app.documents
; app.activeDocument.suspendHistory("replace text", "main()")
}
};
function main () {
var myDocument = app.activeDocument;
var theTexts = readPref ("~/Desktop/text-file2.txt");
var theArray1 = theTexts[0];
var theArray2 = theTexts[1];
for (var b = 0; b < theArray1.length; b++) {
var theString = String(theArray2).split("\\n").join("\r");
replaceText (theArray1, theString)
};
};
////// reoplace text //////
function replaceText (replaceThis, replaceWith) {
// =======================================================
var idreplace = stringIDToTypeID( "replace" );
var desc22 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref3 = new ActionReference();
var idPrpr = charIDToTypeID( "Prpr" );
var idreplace = stringIDToTypeID( "replace" );
ref3.putProperty( idPrpr, idreplace );
var idTxLr = charIDToTypeID( "TxLr" );
var idOrdn = charIDToTypeID( "Ordn" );
var idAl = charIDToTypeID( "Al " );
ref3.putEnumerated( idTxLr, idOrdn, idAl );
desc22.putReference( idnull, ref3 );
var idUsng = charIDToTypeID( "Usng" );
var desc23 = new ActionDescriptor();
var idfind = stringIDToTypeID( "find" );
desc23.putString( idfind, replaceThis );
var idreplace = stringIDToTypeID( "replace" );
desc23.putString( idreplace, replaceWith );
var idcheckAll = stringIDToTypeID( "checkAll" );
desc23.putBoolean( idcheckAll, true );
var idFwd = charIDToTypeID( "Fwd " );
desc23.putBoolean( idFwd, true );
var idcaseSensitive = stringIDToTypeID( "caseSensitive" );
desc23.putBoolean( idcaseSensitive, false );
var idwholeWord = stringIDToTypeID( "wholeWord" );
desc23.putBoolean( idwholeWord, false );
var idignoreAccents = stringIDToTypeID( "ignoreAccents" );
desc23.putBoolean( idignoreAccents, true );
var idfindReplace = stringIDToTypeID( "findReplace" );
desc22.putObject( idUsng, idfindReplace, desc23 );
executeAction( idreplace, desc22, DialogModes.NO );
};
////// read prefs file //////
function readPref (thePath) {
if (File(thePath).exists == true) {
var file = File(thePath);
file.open("r");
var textArray = [];
textArray.push(file.readln().split("|"));
textArray.push(file.readln().split("|"));
file.close();
return textArray;
}
};
Copy link to clipboard
Copied
And… it works!!! After two days trying to figure this out for myself, am am very grateful to you! Thank you!
Just to educate myself. I guess this is the part that tells the script to insert a blank line?
var theString = String(theArray2).split("\\n").join("\r");
If I were to apply this to my simplified script above (post number 40), which I understand more, it should look like this?
Even if you dont find the time for my last question. THANK YOU!
var str= String(id12).split("\\n").join("\r");
Copy link to clipboard
Copied
Actually that line first makes certain the element is a String, then splits it into an Array at the instances of »\n« and joins that Array to a String with »\r« again.
In the code in post 40 the variable »str« would be the whole content of the file, is that intentional?
Copy link to clipboard
Copied
Yes, it's intentional. Will try to make it work also for the script at post 40. If you have tips, they are more then welcomed If I'm not pushing it... Really a hard times with scrips at this point, will try to improve.
The script at post 40 works just as your original script, just for one word in the document. There are no splits for multiple words...
Copy link to clipboard
Copied
Oh, happy day, solved by myself!! Can't belive it
Updated script at post 40, just in case someone needs it in the future.
var file = new File ( "C:\\the-text-file.txt" );
file.open("r");
var open_the_file = file.read();
var str = String(open_the_file).split("\\n").join("\r");
var id3 = stringIDToTypeID( "replace" );
var desc2 = new ActionDescriptor();
var id4 = charIDToTypeID( "null" );
var ref1 = new ActionReference();
var id5 = charIDToTypeID( "Prpr" );
var id6 = stringIDToTypeID( "replace" );
ref1.putProperty( id5, id6 );
var id7 = charIDToTypeID( "TxLr" );
var id8 = charIDToTypeID( "Ordn" );
var id9 = charIDToTypeID( "Al " );
ref1.putEnumerated( id7, id8, id9 );
desc2.putReference( id4, ref1 );
var id10 = charIDToTypeID( "Usng" );
var desc3 = new ActionDescriptor();
var id11 = stringIDToTypeID( "find" );
desc3.putString( id11, "Hello" );
var id12 = stringIDToTypeID( "replace" );
desc3.putString( id12, str );
var id13 = stringIDToTypeID( "checkAll" );
desc3.putBoolean( id13, true );
var id14 = charIDToTypeID( "Fwd " );
desc3.putBoolean( id14, false );
var id15 = stringIDToTypeID( "caseSensitive" );
desc3.putBoolean( id15, true );
var id16 = stringIDToTypeID( "wholeWord" );
desc3.putBoolean( id16, false );
var id17 = stringIDToTypeID( "findReplace" );
desc2.putObject( id10, id17, desc3 );
executeAction( id3, desc2, DialogModes.NO );
Copy link to clipboard
Copied
Hi Apod42! I had APOD 37.
-Noel
Copy link to clipboard
Copied
Hi Noel!! Nice to meet another amateur astronomer here, what a small world I enjoyed a lot of your astrophotos over the years...
Copy link to clipboard
Copied
If the txt file only contains one element couldn’t you just use proper paragraphs in that file instead of »\n«?
Copy link to clipboard
Copied
Hello! Photoshop's find and replace tool does not recognize paragraphs, apparently... If using the script, without \n, I try to replace "Moon" with:
"The Moon is full tonight.
How beautiful!"
I get this: "The Moon is full tonight.How beautiful!"