Question

Basically what's going on is that we are migrating about 50 desktops from XP to 7. I cannot install any extra programs to complete this task. What I am doing is writing a script that copies the Desktop, Favourites, and My Documents, along with a few specific file types from the originating machine to a shared drive for the user. Which later will be able to have all files moved to the new machine they are getting. I'm trying to recursively search through Windows and get all .pst files and other files you will see in the script, and back them up to a folder on the share (but not in a directory structure, I just want all the files in a single directory no matter where they originated from) with the exception of My Documents. Anything they have put in My Documents should be excluded in the search. Anyway, this is what I started with:

@echo off
cls
set USRDIR=
set SHARE=
set /P USRDIR=Enter Local User Directory:  
set /p SHARE=Enter Shared Drive Name:  

set UPATH="c:\Documents and Settings\%USRDIR%"
set SPATH="g:\!MIGRATION"

set ESRI="%UPATH%\Application Data\ESRI"

net use g: /delete
net use g: \\server\%SHARE%
md %SPATH% %SPATH%\GIS %SPATH%\Outlook %SPATH%\Desktop %SPATH%\Documents %SPATH%\Favorites
if exists %ESRI% md %SPATH%\ESRI
md %SPATH%\misc %SPATH%\misc\GISfiles %SPATH%\misc\XMLfiles %SPATH%\misc\CSVfiles

for /R %%x in (*.mxd) do copy "%%x" "%SPATH%\GIS\"
for /R %%x in (*.dbf) do copy "%%x" "%SPATH%\misc\GISfiles\"
for /R %%x in (*.xml) do copy "%%x" "%SPATH%\misc\XMLfiles\"
for /R %%x in (*.csv) do copy "%%x" "%SPATH%\misc\CSVfiles\"
for /R %%x in (*.pst) do copy "%%x" "%SPATH%\Outlook\"
if exist %ESRI% xcopy /y /d /s /i /z %ESRI% %SPATH%\ESRI && echo ESRI YES || ESRI NO
xcopy /y /d /s /i /z "%UPATH%\Desktop" "%SPATH%\Desktop" && echo DESK YES || DESK NO
xcopy /y /d /s /i /z "%UPATH%\My Documents" "%SPATH%\Documents" && echo DOCS YES || DOCS NO
xcopy /y /d /s /i /z "%UPATH%\Favorites" "%SPATH%\Favorites" && echo FAVS YES || FAVS NO

echo "Script Complete!"
pause

I then decided that I wanted to exclude My Documents just in case so I don't end up with a bunch of duplicates where anything they put in My Documents ends up getting copied twice. So I changed that recursive block to this:

for /R %%x in (*.mxd) do xcopy /y /d /z /exclude:"\My Documents\" "%%x" "%SPATH%\GIS\"
for /R %%x in (*.dbf) do xcopy /y /d /z /exclude:"\My Documents\" "%%x" "%SPATH%\misc\GISfiles\"
for /R %%x in (*.xml) do xcopy /y /d /z /exclude:"\My Documents\" "%%x" "%SPATH%\misc\XMLfiles\"
for /R %%x in (*.csv) do xcopy /y /d /z /exclude:"\My Documents\" "%%x" "%SPATH%\misc\CSVfiles\"
for /R %%x in (*.pst) do xcopy /y /d /z /exclude:"\My Documents\" "%%x" "%SPATH%\Outlook\"

Anyway, my question is this, is this the most efficient way of doing this? Is there a better way? I'm curious because I have no one here to bounce ideas or anything off of, I'm the sole on site support here. If someone sees a better way or thinks this is how they would do it, please let me know. There are a bunch more filetypes in there, but I removed most of them so the code sample wasn't so long, left enough to get the point across.

EDIT: Just to make it clear, I am not the IT Department for this organization. I'm a technical support liaison for the department to a separate IT division. Our actual IT department calls this a migration, but it's more or less a simple "lets in stall new machines without doing anything to prepare for it" sort of soup sandwich operation. I can't install, remove, or change the systems in any way, I can only backup the files.

Was it helpful?

Solution

Usually, the best option is reduce processing in batch files to the minimum, leaving as much as possible to commands. But if you have to iterate over the file system several times, it is better to do only one pass and process in batch.

Adapted from a more general batch. I have made changes to adjust to what you need, but somethings more specific (your ESRI folder) are not added. Adapt as needed.

@echo off

    setlocal enableextensions enabledelayedexpansion

    rem Ask for share name
    set /P share=Enter Shared drive name:
    if "%share%"=="" (
        call :error "No share name provided"
        goto endProcess
    )

    rem Configure target of copy
    set target=g:

    rem Connect to target
    net use %target% /delete 
    net use %target% \\server\%share%

    if not exist %target% (
        call :error "No connection to server"
        goto endProcess
    )   

    rem Configure directory by extension
    set extensions=.mxd .dbf .xml .csv .pst
    set .mxd=GIS
    set .dbf=misc\GISFiles
    set .xml=misc\XMLFiles
    set .csv=misc\CSVFiles
    set .pst=Outlook

    rem adjust target of copy to user name
    set target=%target%\!MIGRATION\%username%
    if not exist "%target%" (
        mkdir "%target%"
    )

    rem Configure source of copy
    set source=%userprofile%
    if not exist "%source%" (
        call :error "User profile directory not found"
        goto endProcess
    )

    rem Resolve My Documents folder
    call :getShellFolder Personal
    set myDocPath=%shellFolder%

    if not exist "%myDocPath%" (
        call :error "My Documents directory not found"
        goto endProcess
    )

    rem Ensure target directories exists
    mkdir "%target%" > nul 2>nul
    for %%e in ( %extensions% ) do mkdir "%target%\!%%e!" >nul 2>nul

    rem We are going to filter file list using findstr. Generate temp file
    rem with strings, just to ensure final command line is in limits
    rem This will contain not desired folders/files or anything that will be
    rem copied later

    set filterFile="%temp%\filter.temp"
    (
        echo %myDocPath%
        echo \Temporary Internet Files\
        echo \Temp\
    ) > %filterFile%

    rem Process user profile, excluding My Documents, IE Temp and not needed extensions
    for /F "tokens=*" %%f in ('dir /s /b /a-d "%source%" ^| findstr /v /i /g:%filterFile% ^| findstr /i /e "%extensions%" ') do (
        call :processFile "%%~xf" "%%f"
    )

    rem Now, process "especial" folders

    mkdir "%target%\Documents"
    xcopy /y /d /s /i /z "%myDocPath%" "%target%\Documents"

    call :getShellFolder Desktop
    if exist "%shellFolder%" (
        mkdir "%target%\Desktop"
        xcopy /y /d /s /i /z "%shellFolder%" "%target%\Desktop"
        if errorlevel 1 (
            call :error "Failed to copy desktop files"
        )
    )

    call :getShellFolder Favorites
    if exist "%shellFolder%" (
        mkdir "%target%\Favorites"
        xcopy /y /d /s /i /z "%shellFolder%" "%target%\Favorites"
        if errorlevel 1 (
            call :error "Failed to copy favorites"
        )
    )

    rem Finish
    goto :endProcess

rem ** subroutines *******************************************

:processFile
    rem retrieve parameters 
    rem : %1 = file extension
    rem : %2 = file 
    set ext=%~1
    set file=%~2

    rem manage .something files
    if "%ext%"=="%file%" (
        set file=%ext%
        set ext=
    )

    rem manage no extension files
    if "%ext%"=="" (
        rem WILL NOT COPY
        goto :EOF
    )

    rem determine target directory based on file extension
    set extCmd=%%%ext%%%
    for /F "tokens=*" %%d in ('echo %extCmd%^|find /v "%%" ' ) do set folder=%%d

    if "%folder%"=="" (
        rem file extension not in copy list
        goto :EOF
    )

    copy /y /z "%file%" "%target%\%folder%" >nul 2>nul
    if errorlevel 1 (
        call :error "Failed to copy [%file%]"
    ) else (
        echo %file%
    )

    goto :EOF

:getShellFolder
    set _sf=%~1
    set shellFolder=
    if "%_sf%"=="" goto :EOF
    for /F "tokens=2,*" %%# in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "%_sf%" ^| find "%_sf%"') do (
        set shellFolder=%%$
    )
    goto :EOF


:error
    echo.
    echo ERROR : %~1
    echo.
    goto :EOF   


:endProcess

    endlocal
    exit /b

OTHER TIPS

Try User State Migration Tool from Microsoft - I used it to move around 400 systems in less than 30 days. It takes a bit of setup for the script to run right, but it does a really really good job (and no program to install).

In default mode, it gets all PST files, Document, Desktop, Favorites, and a ton of other folders/registry settings. It also does this for all users on a computer (which can be limited by last login date or number of profiles) as long as the user running it is a local admin.

It may or may not work for what you need, but it's a good choice when designing a migration. It sounds like what you are trying to do can be done with USMT just by removing extra code in the ini files.

This checks and excludes any folder that ends with documents\ (or includes it, so subdirectories too) as IIRC the folder may be called \documents\ or \my documents\ and is case insensitive.

setlocal enabledelayedexpansion
for /R %%x in (*.mxd) do set "check=%%~dpx" & if /i "!check!"=="!check:documents\=!" copy "%%x" "%SPATH%\GIS\"
for /R %%x in (*.dbf) do set "check=%%~dpx" & if /i "!check!"=="!check:documents\=!" copy "%%x" "%SPATH%\misc\GISfiles\"
for /R %%x in (*.xml) do set "check=%%~dpx" & if /i "!check!"=="!check:documents\=!" copy "%%x" "%SPATH%\misc\XMLfiles\"
for /R %%x in (*.csv) do set "check=%%~dpx" & if /i "!check!"=="!check:documents\=!" copy "%%x" "%SPATH%\misc\CSVfiles\"
for /R %%x in (*.pst) do set "check=%%~dpx" & if /i "!check!"=="!check:documents\=!" copy "%%x" "%SPATH%\Outlook\"
endlocal
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top