For loop : variable not taken into account - windows

I have a problem with the batch script below when checking the write permissions on the target folders.
It works well if there are only write-protected folders. But if there are a mix of write-protected folders and non-write-protected folders, it will also run xcopy for the write-protected folders.
I think it has to do with the value assigned to "write_ok" that always keeps the last value.
But how can I fix it ?
Here is my code :
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set BackupDest=D:\backup
for /f "tokens=*" %%I in ('dir /a:d-h /b "%HomeDrive%\users\*" ^| findstr /x /i /l /v /g:"%~dp0exclude_users.txt"') do if exist "%BackupDest%\%%I\" (
echo -----------------------------------------
echo Processing user : %%I
echo -----------------------------------------
echo
:: checking write permissions
copy /y nul "%BackupDest%\%%I\.writable" >nul 2>&1 && set write_ok=1
if defined write_ok (
del "%BackupDest%\%%I\.writable"
xcopy "%%I\Desktop" "%BackupDest%\%%I\Desktop\" /e /i /y
xcopy "%%I\Documents" "%BackupDest%\%%I\Documents\" /e /i /y
) else (
echo Access refused ^(check permissions^)
)
)
pause
exit
Thank you for your help.

You forgot to unset the write_ok variable, so after once it's set, it is always defined.
Just unset it before using it:
:: checking write permissions
set "write_ok="
copy /y nul "%BackupDest%\%%I\.writable" >nul 2>&1 && set write_ok=1
if defined write_ok (
del "%BackupDest%\%%I\.writable"
xcopy "%%I\Desktop" "%BackupDest%\%%I\Desktop\" /e /i /y
xcopy "%%I\Documents" "%BackupDest%\%%I\Documents\" /e /i /y
) else (
echo Access refused ^(check permissions^)
)
Alternatively you can avoid the variable completely:
:: checking write permissions
copy /y nul "%BackupDest%\%%I\.writable" >nul 2>&1 && (
del "%BackupDest%\%%I\.writable"
xcopy "%%I\Desktop" "%BackupDest%\%%I\Desktop\" /e /i /y
xcopy "%%I\Documents" "%BackupDest%\%%I\Documents\" /e /i /y
) || (
echo Access refused ^(check permissions^)
)

Related

How to combine this two "FOR" loops into one?

I'm trying to combine two FOR loops into one.
Here is my code :
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set BackupDest=D:\backup
for /D %%I in ("%HomeDrive%\users\*") do if exist "%BackupDest%\%%~nI\" (
xcopy "%HomeDrive%\users\%%~nI\Desktop" "%BackupDest%\%%~nI\Desktop\" /e /i /y
xcopy "%HomeDrive%\users\%%~nI\Documents" "%BackupDest%\%%~nI\Documents\" /e /i /y
)
for /f "tokens=*" %%I in ('dir /a:d-h /b "%HomeDrive%\users\*" ^| findstr /b /e /i /l /v /g:"%~dp0\bin\exclude_users.txt"') do if not exist "%BackupDest%\%%~nI\" (
echo Destination folder of the user %%~nI is missing
)
I'm note sure if we can do that in this case ?
If yes, how I can achieve this ?
Any help is greatly helpful.
#echo off
setlocal
set "BackupDest=D:\backup"
for /f "tokens=*" %%I in (
'dir /a:d-h /b "%HomeDrive%\users\*" ^| findstr /b /e /i /l /v /g:"%~dp0exclude_user.txt"'
) do (
if exist "%BackupDest%\%%~nxI\" (
xcopy "%HomeDrive%\users\%%~nxI\Desktop" "%BackupDest%\%%~nxI\Desktop\" /e /i /y
xcopy "%HomeDrive%\users\%%~nxI\Documents" "%BackupDest%\%%~nxI\Documents\" /e /i /y
) else (
echo Destination folder of the user %%~nxI is missing
)
)
Use if exist ... (...) else (...) syntax.
A name of a folder uses the modifiers nx, as a folder can be named i.e. firstname.lastname.
If you only use n, then you would only get a part of the folder name firstname.

Batch script to delete all folders except of "Starts with"

I have a folder with several subfolders. Structure is like:
C:\foo
C:\foo\web.foo
C:\foo\web.bar
C:\foo\win.foo
C:\foo\win.bar
C:\foo\mobile.foo
C:\foo\mobile.bar
I sometimes wish to delete the folders with its containing files with following batch script:
rmdir C:\foo /s /q
Here it didn't matter that the whole folder C:\foo was deleted completely.
But now I only want to delete only the subfolders of C:\foo with its containing files, which DO NOT start with "web.".
Do you have any good solution for this?
The following should do the trick, note it's a batch file using the current directory:
#echo off
for /F "delims=" %%D in ('dir /B /AD ^| findstr /V "^web."') do (
echo rmdir %%D /s /q
)
If it's okay remove the echo in front of rmdir.
The dir command just list directory names because of /AD and use a simple name output because of /B. To search on the beginning use findstr with /V. For negation use ^. Further the pipe symbol needs to be escaped ^|.
If you want a dynamic batch script that uses arguments you can use the following, call it via batchname.bat "C:\foo" web. (if it's okay remove the echo in front of rmdir.):
#echo off
set INVARGS=0
if [%1] == [] set "INVARGS=1"
if [%2] == [] set "INVARGS=1"
if %INVARGS% == 1 (
echo echo %0 ^<directory^> ^<directory_prefix^>
goto eof
)
set "folder=%1%"
set "prefix=%2%"
pushd "%folder%"
echo List of folders that should be deleted:
for /F "delims=" %%D in ('dir /B /AD ^| findstr /v "^%prefix%"') do (
echo "%cd%\%%D"
)
popd
:choice
echo.
set /P "c=Are you sure you want to continue [Y/N]?"
if /I "%c%" EQU "Y" goto yes
if /I "%c%" EQU "N" goto eof
goto :choice
:yes
echo.
pushd "%folder%"
for /F "delims=" %%D in ('dir /B /AD ^| findstr /v "^%prefix%"') do (
echo rmdir %%D /s /q
)
popd
:eof
This will remove all files begin with web.
#echo off
setlocal EnableDelayedExpansion
for /f %%F in ('dir /b /s') do (
set "name=%%~nF"
if /i not "!name:~0,4!" == "web." (
rm !name!
)
)

Copying a file to mapped drive not working

I am trying to connect to a network drive, copy a file and move it to another location, and log if it is successful or not. This is what I got so far:
#echo off
#setlocal enableextensions enabledelayedexpansion
if exist Transfer_logfile.txt (
ECHO Y | del Transfer_logfile.txt
)
set LogFile=_logfile.txt
set logg=^> _^&^& type _^&^&type _^>^>%LogFile%
for /F "tokens=*" %%A in (ipaddresses.txt) do (
net use \\%%A\c$\test /USER:test %logg%
echo copying files across to %%A... %logg%
COPY -f -R -Y C:\test\test.exe \\%%A\c$\test\test.exe %logg%
echo Copy completed.. %logg%
net use \\%%A\c$\test /delete /Y %logg%
)
pause
Any help on how to finish this of would be appreciated.
I am struggling to save any errors in the output. If it errors I want it to just save that it failed in output and go on to the next IP in the IP address text file.
I think, I need to wrap an if around the net use checking that the ip address pings first. However this does not work.
#echo off
#setlocal enableextensions enabledelayedexpansion
if exist Transfer_logfile.txt (
ECHO Y | del Transfer_logfile.txt
)
set LogFile=_logfile.txt
set logg=^> _^&^& type _^&^&type _^>^>%LogFile%
for /F "tokens=*" %%A in (ipaddresses.txt) do (
ping -n %%A > NUL
IF ERRORLEVEL 0 (
echo
ELSE goto :skipcopyhost1
net use \\%%A\c$\test %logg%
echo copying files across to %%A... %logg%
COPY -f -R -Y C:\test\test.exe \\%%A\c$\test\test.exe %logg%
echo Copy completed.. %logg%
net use \\%%A\c$\test /delete /Y %logg%
)
pause
Try this not tested batch code:
#echo off
if not exist ipaddresses.txt goto :EOF
setlocal
del /F Transfer_logfile.txt 2>nul
set "LogFile=Transfer_logfile.txt"
for /F %%A in (ipaddresses.txt) do (
%SystemRoot%\System32\ping.exe -n %%A >nul
if errorlevel 1 (
echo %%A is not available in network.>>%LogFile%
) else (
echo Connecting to %%A ...>>%LogFile%
%SystemRoot%\System32\net.exe use X: \\%%A\c$\test /persistent:no /Y 2>&1 >>%LogFile%
echo Copying file to %%A ...>>%LogFile%
copy /B /V /Y C:\test\test.exe X:\test.exe 2>&1 >>%LogFile%
echo Disconnecting from %%A ...>>%LogFile%
%SystemRoot%\System32\net.exe use X: /delete /Y 2>&1 >>%LogFile%
)
echo.>>%LogFile%
)
endlocal
pause
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
copy /?
del /?
for /?
goto /?
if /?
net /?
net use /?
set /?
Further read the Microsoft articles:
Using Command Redirection Operators
Testing for a Specific Error Level in Batch Files
I don't explain all the errors in your code as they are too many.

Windows CMD delete directory

I'm in D:\User Profiles\ and I need to delete directorys located in
D:\User Profiles\---USERNAME---\UPM_Profile\AppData\Local\Mozilla\Firefox\Profiles\*.default
Now here's the question. How can I do this dynamic ?
If I type
dir /ad /b /s D:\User Profiles\*\UPM_Profile\AppData\Local\Mozilla\Firefox\Profiles\*.default
it fails.
---USERNAME--- and *.default needs to be dynamic.
Any ideas `?
Something like:
#echo off
for /d %%i in ("D:\User Profiles\*") do (
call :remove_dirs %%i
)
goto :eof
:remove_dirs
echo %1
for /d %%j in ("%1\UPM_Profile\AppData\Local\Mozilla\Firefox\Profiles") do rmdir %%j
goto :eof

Randomly choose 15 files and copy them to output folder

Must work on XP/Vista/7. Can use batch, VBS, or whatever else anyone with the mentioned O/Ses can run (except PE).
Need to choose 15 random files, and also similarly named folders (which are in a different location), and copy them to their own folder at the same time.
I've scoured google and websites like robvanderwoude.com, and found a few close examples, but I'm too inexperienced to adapt the examples to what I need without going cross-eyed. I'd appreciate it if anyone could point me in the right direction (most efficient/easiest method to use), or some example possibly with a brief explanation I can also learn from.
Layout description:
30 files:
%~dp0\mod\store\XMLs -> %~dp0\mod\0.1.2\map\data
map01_aaa.xml
map02_bbb.xml
map03_ccc.xml
...
map60_zzz.xml
30 folders:
%~dp0\mod\store\models -> %~dp0\mod\0.1.2\sky\stuff
01_aaa_map
02_bbb_map
03_ccc_map
...
60_zzz_map
The code below is what I'm trying to adopt this to, but it only chooses 15 files/folders in order. Tried using the %random% environment var in an equation for SrcMax, but that just chooses a random amount of files and always starts with the first file.
(old code)
rem #ECHO OFF
setlocal ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
SET SrcCount=0
SET SrcMax=15
FOR %%F IN (%~dp0\mod\store\XMLs\*.*) DO IF !SrcCount! LSS %SrcMax% (
SET /A SrcCount += 1
ECHO !SrcCount! COPY %%F %~dp0\mod\0.1.2\map\data\
COPY %%F %~dp0\mod\0.1.2\map\data\
SET FNAME=%%~nF
ECHO XCOPY /s "%~dp0\mod\store\Models\!FNAME:~3!_map" "%~dp0\mod\0.1.2\sky\stuff\!FNAME:~3!_map\"
XCOPY /s "%~dp0\mod\store\Models\!FNAME:~3!_map" "%~dp0\mod\0.1.2\sky\stuff\!FNAME:~3!_map\"
)
I believe this should work.
#echo off
setlocal enabledelayedexpansion
set XMLs_src=.\mod\store\XMLs
set XMLs_dest=.\mod\0.1.2\map\data
set maps_src=.\mod\store\models
set maps_dest=.\mod\0.1.2\sky\stuff
rmdir /q /s "%XMLs_dest%" 2>NUL
rmdir /q /s "%maps_dest%" 2>NUL
mkdir "%XMLs_dest%"
mkdir "%maps_dest%"
for /L %%X in (1,1,15) do (
call :rnd rn
call :xml !rn!
call :map !rn!
)
copy "%XMLs_dest%\*.*" "%XMLs_src%" >NUL
echo d | xcopy /q /f /e /y "%maps_dest%\*" "%maps_src%" >NUL
echo Done.
goto :EOF
:rnd
set c=0
for /d %%I in (%maps_src%\*) do set /a c+=1 >NUL
set /a %1=%RANDOM% * %c% / 32768 + 1 >NUL
goto :EOF
:xml
set c=0
for /f %%I in ('dir /b /o:n "%XMLs_src%"') do (
set /a c+=1 >NUL
if !c!==%1 (
echo %XMLs_src%\%%I -^> %XMLs_dest%\%%I
move "%XMLs_src%\%%I" "%XMLs_dest%" >NUL
goto :EOF
)
)
goto :EOF
:map
set c=0
for /f %%I in ('dir /b /o:n "%maps_src%"') do (
set /a c+=1 >NUL
if !c!==%1 (
echo %maps_src%\%%I -^> %maps_dest%\%%I
echo d | xcopy /q /f /e /y "%maps_src%\%%I" "%maps_dest%\%%I" >NUL
rmdir /q /s "%maps_src%\%%I"
goto :EOF
)
)
goto :EOF
It basically moves to prevent duplication, then copies from destination back to source to restore what was moved away.

Resources