Introduction
This tip will show you how to save time when dumping the content of many CDs and DVDs to a folder by eliminating all desktop application interactions once the process gets going.
Background
Lately, I found myself having the need to move the content of a lot of CDs and DVDs to a folder on a hard disk. This is not a difficult task - but it is tedious. Insert a disc, wait for Explorer to show its content, select all the files and folders, then drag and drop (or right-click, copy/paste) on the target folder. Then wait until the drives are done reading/writing, and repeat.
Obviously, I didn't want this task to monopolize my time, so typically as soon as the copy operation is underway, I switch back to whatever I was doing and I can keep working for the next 10 to 15 minutes, depending on how full the disc is. Once it's done, I have to switch back to Explorer, eject the disc, put the next one in, wait again for the files to show up and drag and drop them on the target folder. Again...easy, but tedious. There's gotta be a way to eliminate at least some of these steps!
Using the Code
Put simply, all that's needed is a script that will read the content of a designated source, copy it to some destination folder, eject the disc, then wait for the next one to be put in before starting the copy operation again. The end user obviously still has to take out the disc and put the next one in, but the script can at least eliminate the need to interact with Explorer to tell it what to copy and where to put it for every disc. That means no need to alt-tab between whatever you're working on and Explorer, and then back. You could even copy files while the computer's monitor is turned off and you're doing something else. Just feed it discs one at a time.
Simply invoke the script (see below) from a PowerShell prompt using something like:
copycd.ps1 D:\ N:\DataDump
This will copy the content of the D: drive to N:\DataDump until you terminate the script with Ctrl-C (or close the PowerShell window).
function CopyAll
{
param(
[string] $source,
[string] $destination
)
if ( !(Test-Path -Path $destination) )
{
New-Item -ItemType Directory -Path $destination
}
if ( !(Test-Path -Path $source) )
{
Write-Host "Source drive is empty"
return
}
robocopy $source $destination /E /DCOPY:DT /COPY:DT
Start-Sleep -Seconds 5
Eject-CD
}
function Eject-CD()
{
Try
{
Write-Host "Ejecting disc..."
$item = (New-Object -ComObject "WMPlayer.OCX.7").CDROMCollection.Item(0)
$item.Eject()
Start-Sleep -Seconds 5
}
Catch
{
Write-Host "Exception ejecting the disc"
}
}
for( ;; )
{
CopyAll $args[ 0 ] $args[ 1 ]
Start-Sleep -Seconds 5
}
In hindsight, it hardly gets any simpler. An infinite for
-loop invokes CopyAll()
, supplying the source and target folder names provided as command-line arguments. Use double-quotes if a path contains a space.
The Test-Path checks are key to deciding whether the copy operation should be started or not (else be ready to handle all sorts of nasty exceptions). If the source folder exists (a disc is in the drive), we invoke robocopy
; after it's done, the media is ejected, and the for
-loop restarts the process, until you terminate the script with Ctrl-C or close the window.
Points of Interest
If you have more than one CD/DVD drive, the Eject-CD
function, as it stands, will blindly send the eject
command to the first one. You can replace "...Item(0)
" with "Item(1)
" or whatever works with your drive. The script certainly could be made more sophisticated by having it figure out on its own what index to use given the source drive named in $args[0]
. But, I was going for simplicity.
I've also spent a lot more time than I'd like to admit looking at different methods to perform the copy operation, each with its own caveats and quirks when it comes to reading from a drive that might not be ready yet, handling a number of different exceptions, etc. In the end, I settled on robocopy
as it's been included with all versions of Windows for nearly a decade now, and it supports plenty of command-line arguments of its own that allow for quite a bit of flexibility, without having to add complex logic to the script, such as deciding what to do when a file by the same name already exists in the target folder, whether to include empty subfolders, etc. If robocopy can do it, take advantage of it--don't make it harder on yourself by making the script more complex.
History
This is the first version of the script.