Stop Custom Scripts: 4 Ways to Move SharePoint Files
At a Glance
- Target Audience
- SharePoint Developers
- Problem Solved
- Losing metadata & version history when copying/moving files via custom scripts
- Use Case
- Library migrations or reorganizing documents/folders across sites
<p>Most developers waste hours writing custom scripts to move documents across SharePoint libraries. It never works perfectly. You write a loop, copy the items over, and suddenly realize you just destroyed the original metadata. Every file looks like it was created by the service account five minutes ago.</p>
<p>Stop overcomplicating your migrations. You do not need a massive custom script. You just need to use the native utility class.</p>
<p>SharePoint 2016 quietly introduced a solution that solves this exact headache. You can leverage the SP.MoveCopyUtil class in JSOM to handle the heavy lifting. It preserves your essential metadata, and it requires barely any code.</p>
<p>The <code>SP.js</code> library gives you four specific methods. Each one requires exactly three parameters to execute: your current context, the full source URL, and the full destination URL.</p>
<p>Here is exactly how to use them.</p>
<h2 id="how-to-copy-a-file-using-javascript">How to Copy a File Using JavaScript</h2><p>You want to duplicate a file without losing its history. The <code>SP.MoveCopyUtil.copyFile</code> method pushes the file to your destination URL while keeping the original author and creation time intact.</p>
<pre><code class="hljs language-javascript"><span class="hljs-keyword">var</span> context = <span class="hljs-variable constant_">SP</span>.<span class="hljs-property">ClientContext</span>.<span class="hljs-title function_">get_current</span>();
<span class="hljs-variable constant_">SP</span>.<span class="hljs-property">MoveCopyUtil</span>.<span class="hljs-title function_">copyFile</span>(context, <span class="hljs-string">"http://sp2016/sitepages/home.aspx"</span>, <span class="hljs-string">"http://sp2016/sitepages/home1.aspx"</span>);
context.<span class="hljs-title function_">executeQueryAsync</span>(<span class="hljs-keyword">function</span>(<span class="hljs-params"></span>){}, <span class="hljs-keyword">function</span>(<span class="hljs-params"></span>){});
</code></pre><p></p>
<h2 id="how-to-copy-an-entire-folder">How to Copy an Entire Folder</h2><p>Moving individual files is fine. Copying an entire directory structure is where things usually break. Use <code>SP.MoveCopyUtil.copyFolder</code> to duplicate the folder and every single file nested inside it.</p>
<pre><code class="hljs language-javascript"><span class="hljs-keyword">var</span> context = <span class="hljs-variable constant_">SP</span>.<span class="hljs-property">ClientContext</span>.<span class="hljs-title function_">get_current</span>();
<span class="hljs-variable constant_">SP</span>.<span class="hljs-property">MoveCopyUtil</span>.<span class="hljs-title function_">copyFolder</span>(context, <span class="hljs-string">"http://sp2016/sitepages/homeFolder"</span>, <span class="hljs-string">"http://sp2016/sitepages/HomeFolder1"</span>);
context.<span class="hljs-title function_">executeQueryAsync</span>(<span class="hljs-keyword">function</span>(<span class="hljs-params"></span>){}, <span class="hljs-keyword">function</span>(<span class="hljs-params"></span>){});
</code></pre><p></p>
<h2 id="how-to-move-a-folder">How to Move a Folder</h2><p>Sometimes you do not want a copy. You need to physically relocate the asset. The <code>SP.MoveCopyUtil.moveFolder</code> method picks up the directory and drops it in the new location.</p>
<pre><code class="hljs language-javascript"><span class="hljs-keyword">var</span> context = <span class="hljs-variable constant_">SP</span>.<span class="hljs-property">ClientContext</span>.<span class="hljs-title function_">get_current</span>();
<span class="hljs-variable constant_">SP</span>.<span class="hljs-property">MoveCopyUtil</span>.<span class="hljs-title function_">moveFolder</span>(context, <span class="hljs-string">"http://sp2016/sitepages/homeFolder"</span>, <span class="hljs-string">"http://sp2016/pages/HomeFolder1"</span>);
context.<span class="hljs-title function_">executeQueryAsync</span>(<span class="hljs-keyword">function</span>(<span class="hljs-params"></span>){}, <span class="hljs-keyword">function</span>(<span class="hljs-params"></span>){});
</code></pre><p></p>
<h2 id="how-to-move-a-single-file">How to Move a Single File</h2><p>For a simple file relocation, the <code>SP.MoveCopyUtil.moveFile</code> method handles the transfer instantly.</p>
<pre><code class="hljs language-javascript"><span class="hljs-keyword">var</span> context = <span class="hljs-variable constant_">SP</span>.<span class="hljs-property">ClientContext</span>.<span class="hljs-title function_">get_current</span>();
<span class="hljs-variable constant_">SP</span>.<span class="hljs-property">MoveCopyUtil</span>.<span class="hljs-title function_">moveFile</span>(context, <span class="hljs-string">"http://sp2016/sitepages/home1.aspx"</span>, <span class="hljs-string">"http://sp2016/pages/home1.aspx"</span>);
context.<span class="hljs-title function_">executeQueryAsync</span>(<span class="hljs-keyword">function</span>(<span class="hljs-params"></span>){}, <span class="hljs-keyword">function</span>(<span class="hljs-params"></span>){});
</code></pre><p></p>
<p>You do not have to write this in JavaScript if you prefer C#. The equivalent CSOM utility exists under <code>Microsoft.SharePoint.Client.MoveCopyUtil</code>. It shares the same underlying logic but uses a slightly different parameter count.</p>
<p>And if you are working in the cloud, these exact APIs are fully supported in SharePoint Online.</p>
<p>Stop fighting the platform. Use the native tools. Save your time for the actual hard work.</p>
