Copy link to clipboard
Copied
We’re facing a bit of a challenge after trying to move our illustrator files from Dropbox to Google Drive.
We have 1000s of Adobe Illustrator documents containing lots of linked images, the beginning of the path always looks similar to this currently :
C:\Users\username\Dropbox\Media\Files
But after the move, the paths will change to:
C:\Users\username\GoogleDrive\MediaDrive\Files
fixing these links one by one isn't really an option given the sheer number. anyone faced this before and scripted their way out or something like that?
Bulk change links seems to be quite a highly reqeusted feature
Copy link to clipboard
Copied
Hi @paul33910816rb6v, I wrote a script a while back that solved this type of problem on a smaller scale. Use it like this:
1. configure the script (I've configured it for your case above—but will need checking). Configure by editing these lines:
findWhat: 'Users/username/Dropbox/Media/Files',
changeTo: 'Users/username/GoogleDrive/MediaDrive/Files',
(you might need to change my forward slashes to backslashes for Windows, if you do, you'll need to escape them with another backslash; eg. 'Users\\username ...'. I can't test this because I don't have Windows here).
2. open a bunch of illustrator documents.
3. run script—will attempt to relink any placed items to the revised path.
By default, it doesn't save the documents, just attempts the relinking, but when you are confident it is working, you can do:
// warning: back up files before using
var SAVE_AND_CLOSE = true;
Let me know if it helps—try it on just a few documents to start with!
- Mark
/**
* Relinker.js
* for Adobe Illustrator
*
* @author m1b
* @version 2024-04-07
* @discussion https://community.adobe.com/t5/illustrator-discussions/quot-re-link-to-new-path-quot-script/m-p/12776878
*
* with help from advice found here:
* https://community.adobe.com/t5/illustrator/get-broken-file-path-of-rasteritem/td-p/9794237
*
* Limitations:
* • only relinks if the new path points to a valid file
* • document must be saved before relinking to ensure
* xmp manifest is up-to-date (script handles this)
*
* Notes:
* • the find/change is performed on the complete path,
* including filename and file extension
* • findWhat can be String or RegExp
* • onlyChangeBrokenLinks means don't do the relinking
* if the link isn't broken
* • showResults means show an alert with result stats
*
*/
(function () {
var findChanges = [
{
findWhat: 'Users/username/Dropbox/Media/Files',
changeTo: 'Users/username/GoogleDrive/MediaDrive/Files',
},
];
// warning: back up files before using
var SAVE_AND_CLOSE = false;
var docs;
// all open documents
docs = addCollectionToArray(app.documents);
for (var i = docs.length - 1; i >= 0; i--) {
// relink
findChangeInLinkedFilePaths(findChanges, docs[i]);
if (SAVE_AND_CLOSE) {
docs[i].save();
docs[i].close();
}
}
/**
* Perform find/changes on link paths.
* New link paths must resolve to real files.
* @author m1b
* @version 2023-02-01
* @param {Array<Object>} findChanges - the find/change details, eg. [ {findWhat: 'this', changeTo: 'that' } ].
* @param {Document} [doc] - an Illustrator Document (default: active document).
* @param {Boolean} [onlyChangeBrokenLinks] - whether to only process broken links (default: false).
* @param {Boolean} [automaticallySaveDocumentBeforeRelinking] - whether to automatically save document *without asking* before processing (default: false).
* @param {Boolean} [showResults] - whether to show results (default: true).
*/
function findChangeInLinkedFilePaths(findChanges, doc, onlyChangeBrokenLinks, automaticallySaveDocumentBeforeRelinking, showResults) {
doc = doc || app.activeDocument;
showResults = showResults !== false;
// must save document before relinking to ensure the xmp manifest is up-to-date
if (!doc.saved)
if (automaticallySaveDocumentBeforeRelinking || confirm('Document "' + doc.name + '" must be saved before relinking. Continue?', false, 'Save Document'))
doc.save();
else
return;
// get all the placedItems
var items = doc.placedItems,
manifestPaths = getLinkedFilePaths(doc),
relinked = [],
notFound = [],
notChanged = [];
for (var i = 0; i < manifestPaths.length; i++) {
var newPath = manifestPaths[i];
// do the find/changes
for (var j = 0; j < findChanges.length; j++)
var newPath = newPath.replace(findChanges[j].findWhat, findChanges[j].changeTo);
var filename = newPath.split('/').pop(),
item = items[i],
success = false;
if (newPath === manifestPaths[i]) {
notChanged.push(filename);
continue;
}
var linkIsValid;
try {
linkIsValid = item.file != undefined;
// current link is okay
} catch (error) { }
if (
!(linkIsValid && onlyChangeBrokenLinks)
|| linkIsValid
)
// attempt to relink
success = relinkPlacedItem(item, newPath);
if (success)
relinked.push(filename);
else
notFound.push(filename);
}
// report
app.redraw();
if (showResults) {
var report = ['Relinker results'];
if (relinked.length > 0)
report.push('Relinked:\n' + relinked.join('\n'));
else
report.push('No files relinked.');
if (notFound.length > 0)
report.push('Link didn\'t exist:\n' + notFound.join('\n'));
if (notChanged.length > 0)
report.push('Ignored:\n' + notChanged.join('\n'));
alert(report.join('\n\n'));
}
/**
* Relinks a placed item.
* @param {PlacedItem} item - an Illustrator PlacedItem.
* @param {String} path - the path to a placeable file.
* @returns {Boolean} - success?
*/
function relinkPlacedItem(item, path) {
if (File(path).exists) {
item.file = new File(path);
return true;
}
};
};
/**
* Returns all the paths from the
* document's linked file XMP manifest.
* @param {Document} doc - an Illustrator Document.
* @returns {Array<String>} - array of the paths.
*/
function getLinkedFilePaths(doc) {
var manifestPaths = [],
items = doc.placedItems;
// collect the paths of all the placedItems
if (ExternalObject.AdobeXMPScript == undefined)
ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
var xmp = new XMPMeta(doc.XMPString),
manifestItemCount = xmp.countArrayItems(XMPConst.NS_XMP_MM, 'Manifest');
// // sanity check
// if (manifestItemCount != items.length)
// throw ('Aborting: Manifest item count does not match placed item count.');
// collect the paths
for (var i = 0; i < manifestItemCount; i++) {
// get the path from the document's manifest
var xpath = 'xmpMM:Manifest[' + (i + 1) + ']/stMfs:reference/stRef:filePath',
path = xmp.getProperty(XMPConst.NS_XMP_MM, xpath).value;
manifestPaths.push(path);
}
return manifestPaths;
};
/**
* Adds items of an Illustrator collection
* to a given Array.
* @param {collection} collection - eg. PlacedItems, or Documents.
* @param {Array} [array] - the array to add to (default: empty array).
* @returns {Array}
*/
function addCollectionToArray(collection, array) {
array = array || [];
for (var i = 0; i < collection.length; i++)
array.push(collection[i]);
return array;
};
})();
Copy link to clipboard
Copied
Another thought: opening a bunch of old files will very likely end up with many [Converted] documents. The script probably won't handle these until they are saved first—and the save and close *definitely* won't work on these ones. It is possible for the script to handle these but it is more work.
- Mark