Batch copy and reopen itself on new location - batch-file

My batch script can not be run from network source, that's why it's gonna make a copy of itself to the desktop and starts the new copy, on finish it's deleting the copy.
:: Check location
if "%~dp0" == "%userprofile%\Desktop\" goto:eof
xcopy /I /Y "%~dpnx0" "%userprofile%\Desktop\" >nul 2>&1
start "new window" cmd /c %userprofile%\Desktop\batchname.bat
exit
That works fine, my issue is, %cd% or %0 is not updated and is still acting like the original script. Shows the location of the original script.
How can I check the location, make a self-copy to the desktop and start it, like it was double-clicked within windows? Because the script only fails, if it's started through the original script of the share.
What happens:
Starting script XYZ.bat from network share
Script notices not being located on desktop
Script does self-copy to desktop
Script runs copy from desktop
Script ends
Copy launched from original script
Script located on desktop >> fine
Script reads infos of script header:
for /F "tokens=3-8 delims= " %%a in ('findstr /B /C:":: Drive:" "%~dpnx0"') do (
Script fails because %~dpnx0 contains path of original script which is unavailable because all network shares are removed at this point
Any suggestions?
PS: I'm new here, I hope my English is understandable. Cheers
EDIT:
Thanks for the help, the thing with the path is fixed now and the script works fine, as long as I don't turn on the "remove all existing drives" function. If I do so the following happens:
Previous steps taken:
Script checks location and copy itself to the users desktop and starts from there, also all drives are removed, than it fails on the findstr thingy with the error:
[Drive-Mapper:] All map drives removed
[Drive-Mapper:] Mapping drives now:
Das aktuelle Verzeichnis ist ungültig. The current
folder does not exist
[Drive-Mapper:] Successfully finished << I wish..
Drücken Sie eine beliebige Taste . . . Press any key to continue
The Mapping function:
:mapdrives
%say% Mapping drives now:
set errorcount=0
for /F "tokens=3-8 delims= " %%a in ('findstr /B /L /C:":: Drive:" "%~f0"') do (
REM echo Server=%%a User=%%b Letter=%%c drive=%%d nick=%%e
REM if "%%b" == "all" OR if "%%b" == "%username%" (
if "%%b" == "all" (
>nul 2>&1 net use %%c: \\%%a\%%d /persistent:yes
if errorlevel 1 (%say2% Failed %%c: \\%%a\%%d & set /a errorcount=errorcount+1) else (
if "%%e" == "" (
:: Rename without nick
>nul 2>&1 reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\##%%a#%%d /v _LabelFromReg /d "%%d (%%a)" /f
%say2% Successfully %%c: \\%%a\%%d
) else (
:: Rename with nick
>nul 2>&1 reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\##%%a#%%d /v _LabelFromReg /d "%%e (%%a)" /f
%say2% Successfully %%c: \\%%a\%%d # %%e
)
)
)
if "%%b" == "%username%" (
>nul 2>&1 net use %%c: \\%%a\%%d /persistent:yes
if errorlevel 1 (%say2% Failed %%c: \\%%a\%%d & set /a errorcount=errorcount+1) else (
if "%%e" == "" (
:: Rename without nick
>nul 2>&1 reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\##%%a#%%d /v _LabelFromReg /d "%%d (%%a)" /f
%say2% Successfully %%c: \\%%a\%%d
) else (
:: Rename with nick
>nul 2>&1 reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\##%%a#%%d /v _LabelFromReg /d "%%e (%%a)" /f
%say2% Successfully %%c: \\%%a\%%d # %%e
)
)
)
%sf_wait2%
)
%sf_wait%
if "%errorcount%" == "0" (%say% Successfully finished) else (%say% Warning %errorcount% Errors!!)
%say2% & pause
goto:eof
Script crabs infos from batch header:
:: - Force - Deleting drives (0=No,1=Yes)
set force_del_drives=1
:: - Force - Kill Explorer (0=No,1=Yes)
set force_kill_explorer=1
::----------------------------------------------------------------------------------------
:: HINT SERVER USER LETER DRIVE NICKNAME (IF NOT USING DRIVENAME)
:: Drive: server all H Home My Home
:: Drive: server all V Drive1
:: Drive: server all M Drive2
::----------------------------------------------------------------------------------------
:: -Drive: server user I DisabledDrive
:: Drive: server user K Drive4
:: Drive: server user Z Homes All Homes
PS: If I run the script from c:\ it will copy itself to desktop and runs perfectly, it also works like I said, if I dont remove the network drive the script originaly was executed from.
Any ideas?

#echo off
setlocal
:: Check location
if not exist "%userprofile%\Desktop\" (
>&2 echo Desktop folder not exist
exit /b 1
)
if "%~dp0" == "%userprofile%\Desktop\" goto :main
xcopy /I /Y "%~f0" "%userprofile%\Desktop\" >nul 2>&1
start "new window" "cmd /c "%userprofile%\Desktop\%~nx0""
goto :eof
:main
echo %~f0
pause
goto :eof
Added check for Desktop folder as it is a Shell Folder and may
not exist in that location.
Logic changed to go to :main label if location is Desktop folder.
Command of start modified to handle the script name and extension
without hard coding a name and extension.

Related

move and Rename file to folder Powershell

I have some pdf's in a folder that I need to organize them like this:
PDF name: 123.12.123.pdf ; 102030_01.pdf; 102030_02.pdf; 123.4512.34561.23412.pdf
Now I need to create folders with the filename (without the characters removed, ex: 12345123456123412) and rename them to the following pattern: ex: P12345123456123412_V1_A0V0_T07-54-369-664_S00001.pdf
for this I have used the following code which works very well:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
If "%~1" == "" GoTo :EOF
For %%G In (%*) Do (For %%H In ("%%~G") Do If "%%~aH" Lss "-" (
Echo Error! %%G no longer exists.
%SystemRoot%\System32\timeout.exe /T 2 /NoBreak 1>NUL
) Else If "%%~aH" GEq "d" (For %%I In ("%%~G\*.pdf") Do Call :Sub "%%~I"
) Else If /I "%%~xG" == ".pdf" (Call :Sub "%%~G"
) Else (Echo Error! %%G is not a PDF
%SystemRoot%\System32\timeout.exe /T 2 /NoBreak 1>NUL))
GoTo :EOF
:Sub
Set "basename=%~n1"
Set "basename=%basename:.=%"
MD "%~dp1%~n1" 2>NUL
If Not ErrorLevel 1 Move /Y %1 "%~dp1%~n1\P%basename:-=%_V1_A0V0_T07-54-369-664_S00001_Volume%~x1"
Exit /B
I drag the pdfs into the .bat and it does the adjustment.
It happens that there is a case that I am not able to handle. Some pdfs need to be in the same folder, for example in the following case:
PDF name: 102030_01.pdf; 102030_02.pdf;
Note that the pdfs have the same number, only after the _ that we have the difference. In this case you would need to create a folder with the name:102030
And move the two files into it, modifying their name as follows:
102030_01.pdf -> P102030_V1_A0V0_T07-54-369-664_S00001.pdf
102030_02.pdf -> P102030_V1_A0V0_T07-54-369-664_S00002.pdf
Could anyone help?
:Sub
Set "basename=%~n1"
Set "basename=%basename:.=%"
if /i "%basename%" neq "%basename:_=%" goto sub2
MD "%~dp1%~n1" 2>NUL
If Not ErrorLevel 1 Move /Y %1 "%~dp1%~n1\P%basename:-=%_V1_A0V0_T07-54-369-664_S00001_Volume%~x1"
Exit /B
:sub2
for /f "tokens=1*delims=_" %%b in ("%basename%") do (
MD "%~dp1%%b" 2>NUL
ECHO Move /Y %1 "%~dp1%%b\P%basename:-=%_V1_A0V0_T07-54-369-664_S000%%c_Volume%~x1"
)
Exit /B
Always test on dummy data first.
This code echoes the proposed move. After verification, remove the echo keyword to activate.
Caution: My reading of the code is that - should be removed from the basename in the new name, and that _Volume should be appended to the name part, which is not shown in your examples.
Essentially, if the basename contains _ then goto sub2.
sub2 partitions the name in basename, assigning the first part to %%b and the second to %%c (See for /? from the prompt for documentation)
Then the directory is created
The md will object if the directory already exists, hence the 2>nul in the original code (suppresses error messages)
If md found that error in the original then this appears to be a problem, so the move is not executed. In the new version, it is expected that the directory may already exist, so the errorlevel processing has been removed.

Make Batch file try Drives D/E/F/H and have it copy from G to them

#echo on
set choice=
:D
if exist D: (set choice=D:) if exist (choice=D:) goto copyG else goto E
:E
if exist E: (set choice=E:) if exist (choice=E:) goto copyG else goto F
:F
if exist F: (set choice=F:) if exist (choice=F:) goto copyG else goto H
:H
if exist H: (set choice=H:) if exist (choice=H:) goto copyG
:copyG
xcopy /e /y G:\2019-Year10\*.* "%choice%"
pause
:removed
echo removed
This is my current code.
But is does not copy the files to the USB from the G drive.
Is there a way to fix this?
Edit:
Thanks got it working in the end i used this
#echo off
echo.
echo Finding Drive to copy work from "G:\2019-Year10"
echo.
for %%i in (D: E: F: H:) do (
if exist %%i set drive=%%i
)
xcopy /e /y "G:\2019-Year10\*.*" "%drive%\2019-Year10\"
echo.
echo Files coped to "%drive%"
echo.
echo.
echo Remove %drive% Drive
:removle_of_drive
if exist %drive% (goto removle_of_drive) else exit
It knows when you take out the USB and closes the batch file, and gives you more info on what it is doing
thanks for the help: Gerhard Barnard
So here we can use wmic to determine the disk type. Note!!! If you have more than one USB attached, this will not do as intended:
#echo off
for /F "tokens=1-4" %%a in ('wmic logicaldisk get caption^,description^,drivetype 2^>nul') do (
if %%l equ 2 (
echo xcopy /e /y "G:\2019-Year10\*.*" "%%d"
)
)
pause
Also Note I added echo to the xcopy line to simulate the command, only remove echo to perform the ACTUAL xcopy command once you are happy that it will do what you want it to.
But to basically show you how the choice one should work (as per your example):
CHOICE /C DEFH /M "Choose driveletter "
if errorlevel 4 set "Drive=H:"
if errorlevel 3 set "Drive=F:"
if errorlevel 2 set "Drive=E:"
if errorlevel 1 set "Drive=D:"
echo xcopy /e /y "G:\2019-Year10\*.*" "%Drive%\"
Or to automate it based on your know drive letters, instead of detecting it like the first example (as per your example)
#echo off
for %%i in (D: E: F: H:) do (
if exist %%i echo xcopy /e /y "G:\2019-Year10\*.*" "%%i\"
)

How to get to users %APPDATA% when running as system user from a batch file

Deploying applications via SCCM. Currently trying to deploy Wireshark and I am 1st trying to create the directory then copy over a preference file to the users %APPDATA%. The preference file basically stops the application from checking for auto updates.
Reason I need to create the directory is because it does not exist until Wireshark is launched for the 1st time.
Issue is that when doing this, SCCM is deploying as a system user so %APPDATA% goes to directory C:\Windows\System32\config\systemprofile\AppData\Roaming\
But I would like to get to C:\Users\SPECIFIC USER\AppData\Roaming
I am deploying the application with a batch file:
Wireshark-win64-2.4.6.exe /S
mkdir %APPDATA%\Wireshark\
xcopy preferences %APPDATA%\Wireshark
This will work locally on my own machine but if I run under PSEXEC (like SCCM would) then it will end up in the incorrect directory.
I am new to creating applications within SCCM as well as using batch files to deploy so please include details if possible. Regardless I appreciate the help!
Done with using getprofiles.cmd to echo the profiles and using main.cmd
with a for loop to process the profile paths.
main.cmd:
#echo off
setlocal
:: Install Wireshark.
echo Wireshark-win64-2.4.6.exe /S
:: Update Wireshark app data in user profiles.
for /f "tokens=*" %%A in ('getprofiles.cmd "\AppData\Roaming"') do (
call :skip_profile "%%~A" "\\Administrator\\" "\\MSSQL\$SQLEXPRESS\\" || (
echo mkdir "%%~A\Wireshark\"
echo xcopy preferences "%%~A\Wireshark"
)
)
exit /b
:skip_profile
for %%A in (%*) do (
if not "%%~A" == "" if /i not "%%~A" == "%~1" (
echo "%~1"| findstr /i "%%~A" >nul 2>nul
if not errorlevel 1 (
echo Skip account "%~1"
exit /b 0
)
)
)
exit /b 1
getprofiles.cmd:
#echo off
setlocal
if "%~1" == "/?" goto :help
:: ProfileList key that contains profile paths.
set "ProfileListKey=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
:: Get profiles directory path.
set "ProfilesDirectory="
for /f "tokens=1,3" %%A in (
'reg query "%ProfileListKey%" /v "ProfilesDirectory"'
) do if /i "%%~A" == "ProfilesDirectory" call set "ProfilesDirectory=%%~B"
if not defined ProfilesDirectory (
>&2 echo ProfilesDirectory is undefined
exit /b 1
)
:: Search all profile paths in profiles directory and echo existing paths appended with the 1st script argument.
for /f "delims=" %%A in (
'reg query "%ProfileListKey%"'
) do call :ProfilePath "%%~A" "%~1"
exit /b
:ProfilePath
setlocal
set "arg1=%~1"
:: Validate 1st call argument is a profile subkey.
if not defined arg1 exit /b 1
if /i "%arg1%" == "%ProfileListKey%" exit /b 1
if "%arg1:~,1%" == " " exit /b 1
:: Echo existing profile paths with defined 2nd argument appended.
for /f "tokens=1,3" %%A in (
'reg query "%arg1%" /v ProfileImagePath^|find /i "%ProfilesDirectory%"'
) do (
if "%%~A" == "ProfileImagePath" (
if exist "%%~B%~2" echo "%%~B%~2"
)
)
exit /b
:help
echo Prints profile paths from the registry that exist in the Profiles Directory.
echo 1st argument can be a path to be appended to the profile path.
echo i.e. "\AppData\Roaming" is appended to become "C:\Users\...\AppData\Roaming".
exit /b
The script main.cmd echoes the results for testing. Remove the echoes
to actually use if commands are valid.
The ProfileList key in the registry stores the path to find the
profiles and has subkeys with data such as path of each profile on
the machine.
main.cmd can avoid profiles such as Administrator and MSSQL$SQLEXPRESS.
The called label :skip_profile takes the profile path as 1st argument.
Following arguments are for patterns and if matched, will be a skipped
profile.
findstr is being used for checking the profile path for a match with
regular expressions so use findstr /? for syntax requirements.
Case is set as insensitive as to use of /i.
The getprofiles.cmd script gets the ProfilesDirectory path which
is where the user profile folders can be found. It then querys the key
to get the profile keys by using the called label of :ProfilePath.
The label checks if the ProfilesDirectory path is found in each
profile path found. It then checks if the path exists before echoing
the path. If the optional 1st parameter is passed, then it will be
appended and the path will be validated as that path.
A test outputs:
Wireshark-win64-2.4.6.exe /S
mkdir "C:\Users\Michael\AppData\Roaming\Wireshark\"
xcopy preferences "C:\Users\Michael\AppData\Roaming\Wireshark"
which seems OK as I only have 1 user profile on my current machine.
You could probably merge the code together to make just 1 script though
I decided to leave getprofiles.cmd as reusable for other uses.
Here's a batch file that may help you. It creates the directory you tell it in all user's %APPDATA% directories it finds if you don't specify a username, or creates the directory in only the specific user's %APPDATA% directory if you do specify a username.
#ECHO OFF
SETLOCAL
SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION
SET BAT=%~NX0
SET ROOTDIR=C:\Users
IF "%~1" == "" (
GOTO USAGE
)
SET "DIR=%~1"
SET "USER=%~2"
IF NOT "%USER%" == "" (
IF EXIST %ROOTDIR%\%USER%\AppData\Roaming\ (
IF NOT EXIST "%ROOTDIR%\%USER%\AppData\Roaming\%DIR%" (
MKDIR "%ROOTDIR%\%USER%\AppData\Roaming\%DIR%"
ECHO Created %ROOTDIR%\%USER%\AppData\Roaming\%DIR%
)
)
GOTO :EOF
)
FOR /F "DELIMS=" %%D IN ('DIR /A:D /B %ROOTDIR%') DO (
IF EXIST %ROOTDIR%\%%D\AppData\Roaming\ (
IF NOT EXIST "%ROOTDIR%\%%D\AppData\Roaming\%DIR%" (
MKDIR "%ROOTDIR%\%%D\AppData\Roaming\%DIR%"
ECHO Created %ROOTDIR%\%%D\AppData\Roaming\%DIR%
)
)
)
GOTO :EOF
:: --------------------------------------------------------------------------
:USAGE
ECHO.
ECHO A batch file that creates a directory in every user's %%APPDATA%% directory
ECHO if no username is specified or creates the directory only for the specific
ECHO user if the username is specified.
ECHO.
ECHO Usage: %BAT% ^<directory^> [username]
GOTO :EOF
Find the owner of the EXPLORER.EXE process:
for /f "TOKENS=1,2,*" %%a in ('tasklist /FI "IMAGENAME eq explorer.exe" /FO LIST /V') do if /i "%%a %%b"=="User Name:" (set domain_user=%%c)
for /f "TOKENS=1,2 DELIMS=\" %%a in ("%domain_user%") do set domain=%%a && set LoggedInUserID=%%b
 
for /f "TOKENS=1,2,*" %%a in ('tasklist /FI "IMAGENAME eq explorer.exe" /FO LIST /V') do if /i "%%a %%b"=="User Name:" (set domain_user=%%c)
for /f "TOKENS=1,2 DELIMS=" %%a in ("%domain_user%") do set domain=%%a && set LoggedInUserID=%%b

Check for new folder after running bat commands

Is there a way to check if a new folder (exact name is unknown) has been created inside a specific parent folder as a result of running previous commands in bat file? If yes - run one more command with the full path to a new folder as an argument to that command.
Right now I am using a folder monitoring software to run another bat if new folder is created. I would like to have just one script performing both tasks.
Thank you for your help.
change the root_folder location on the second line
#echo off
set "root_folder=C:\something"
setlocal enableDelayedExpansion
set counter=1
for /d /r "%root_folder%" %%a in (*) do (
set "dirs[!counter!]=%%~sa" >nul
set /a counter=counter+1
)
rem ############################
rem # call your code here !!! #
rem ############################
call commands.bat
rem for /l %%l in (1,1,!counter!) do (
rem dir /x /b /s /a:d "%root_folder%" | findstr /i "dirs[%%l]"
rem )
set flag=0
for /d /r "%root_folder%" %%a in (*) do (
set dirs[|find /i "%%~sa" >nul 2>nul ||(
echo "%%~sa" is a new folder
set flag=1
)
)
if %flag% equ 0 (
echo no new folders
)

Excluding a folder in a recursive copy in Batch

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.
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
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

Resources