We have a batch script that removes files (del) and directories (rd). Does anyone know how to halt (fail) execution of the script if any of these delete statements fail? They could fail if a file/directory is locked by Windows. Thanks.
Update
Statements I'm using:
Del: del *.* /S /Q
RD: FOR /D %%G in (*) DO RD /s /q %%G
For deleting the files, you can first try to ren (rename) the file.
ren will set ERRORLEVEL to 1 if the file is locked. Add quotes around filename.
#echo OFF
:: Delete all files, but exit if a file is locked.
for %%F in (*.*) do (
#echo Deleting %%F
ren "%%F" tmp 2> nul
if ERRORLEVEL 1 (
#echo Cannot delete %%F, it is locked.
exit /b 1
)
del tmp
)
I suspect you may be able to do the same thing for directories, but I can't seem to figure out how to get a directory locked so I can test. The following may work:
:: Remove all directories, but exit if one is locked.
FOR /D %%G in (*) DO (
#echo Removing %%G
ren "%%G" tmpdir 2> nul
if ERRORLEVEL 1 (
#echo Cannot remove %%G, it is locked
exit /b 1
)
RD /s /q tmpdir
)
DEL doesn't return an errorlevel if the file is locked. I just did a test with excel file and I saw a zero (on Windows XP).
It might be better to use IF EXIST for the file to be deleted after you do the delete.
del file.txt
if exist file.txt ECHO "FAIL"
AFTER EDIT
Disclaimer: I have no idea how this performs...
You could do this for the files
DIR /B /S /A-d > c:\filestodelete.txt
del *.* /S /Q
FOR /F %%i in (c:\filestodelete.txt) DO (
IF EXIST %%i ECHO %%i STILL EXISTS
)
then for the directories
DIR /B /S /Ad > c:\directoriestodelete.txt
FOR /D %%G in (*) DO RD /s /q %%G
FOR /F %%i in (c:\directoriestodelete.txt) DO (
IF EXIST %%i ECHO %%i STILL EXISTS
)
EDIT: Right, so del does not set the ERRORLEVEL correctly. See ERRORLEVEL on DEL and Windows delete command can fail silently
PREVIOUS (incorrect) SOLUTION
You should check the errorlevel.
For example:
del file.txt
if errorlevel 1 goto FAIL
:PASS
echo Worked!
goto :END
:FAIL
echo Failed!
exit /B 1
:END
Here's my preferred way to check for errors while deleting files. We redirect the "error output" (standard file "2") to a file (e.g. delCmd.err). Then we use the FOR command as a way to get access to the ~z "file size" operater. If the size of the output file is not 0, then we know that "del" got an error... we display the error with the "type" command and exit the batch file with a non-zero error code:
del unwanted.txt 2> delCmd.err
FOR /F "usebackq" %%A IN ('delCmd.err') DO set size=%%~zA
if not "%size%"=="0" (
echo Error deleting unwanted.txt
type delCmd.err
exit /B 1
)
Here is a shorter version of the result monitoring variant. This is using 2>&1 trick to redirect stderr to stdout and for /f to check for any output.
#echo off
setlocal
set error=0
for /f %%i in ('del notepad2.exe 2^>^&1') do set error=1
echo %error%
Just for your information. The DEL command does return an error code if a serious error occurs, however it's behavior is way beyond our intuition that people would simply believe that the error code doesn't work at all.
This is what I've tested in DEL command in Windows 7:
Successful deletion of all files: 0 (of course)
Some files deleted, some files missing: 0 (intuition expects 1)
Deletion failure due to no permission or a read-only medium: 0 (intuition expects ≥ 1)
Non-existent drive or drive not ready (such as no CD on a CD-ROM drive): 1 (yes, you get it, but I will expect a higher error code)
Invalid path: 1 (I will expect a higher error code, too)
And, if you specify a list of files to DEL command, where at least one of the files fit the last two kinds of error mentioned above, then none of the files in the list will be deleted at all.
There is a script that will work like a charm.
It tests deletion failure by testing the existence of the supposedly deleted file/directory.
The output will be an existing c:\mydirectory with completely empty content.
Any error breaks the process and is reported.
The only downside is that directories are removed recursively, because there is no simple way to start deleting directories starting with the most "sub" directories.
#echo OFF
set path_to_clean=c:\mydirectory
#echo -Deleting Files
dir /A-D /S /B %path_to_clean%\* > fileslist.txt
for /F %%F in (fileslist.txt) do (
#echo Deleting %%F
del %%F 2> nul
if exist %%F (
#echo Cannot delete %%F, it is locked.
goto errorhandling
)
)
del fileslist.txt
#echo -Deleting Files done
#echo -Deleting Directories
dir /AD /B %path_to_clean%\* > directorieslist.txt
for /F %%D in (directorieslist.txt) do (
#echo Deleting %path_to_clean%\%%D
rmdir /S /Q %path_to_clean%\%%D 2> nul
if exist %path_to_clean%\%%D (
#echo Cannot delete %path_to_clean%\%%D. This folder or one of its sub-directories is locked.
goto errorhandling
)
)
del directorieslist.txt
#echo -Deleting Directories done
:errorhandling
rem some code here
These seem to work for me:
RD:
FOR /D %d IN (*) DO ( RD /S /Q "%d" & IF EXIST "%d" EXIT /B 1 )
DEL:
FOR %f IN (*.*) DO ( DEL /Q "%f" & IF EXIST "%f" EXIT /B 1 )
No idea about the performance though.
You can add flag /F to DEL for a "force delete" mode.
For rd and rmdir you can do
rd "some directory" || rem
this will set the errorlevel correctly - see
Hi This should work as well
#echo off
for /f %%i in ('del notepad2.exe 2^>^&1') do set ERRORLEVEL=1
IF %ERRORLEVEL%=1 then exit
Related
I have a batch file, that constantly checks to see if there are any files in a directory:
#echo off
cls
mode 15,5
cd C:\Users\Toni\Downloads\
goto mark
:mark
set var=2
dir /b /a "Downloads\*" | >nul findstr "^" && (goto exin) || (goto mark1)
goto mark
:mark1
cls
#ping -n 10 localhost> nul
goto mark
:exin
start /B C:\Users\Toni\Downloads\Test\download.bat
exit
if ther are any files in this folder, it moves them.
#echo off
cls
cd C:\Users\Toni\Downloads\Downloads
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.rar C:\Users\Toni\Downloads\Archive
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.zip C:\Users\Toni\Downloads\Archive
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.exe C:\Users\Toni\Downloads\Setups_usw
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.msi C:\Users\Toni\Downloads\Setups_usw
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.mp3 E:\-_MUSIC_-\Musik
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.wav E:\-_MUSIC_-\Musik
xcopy /S /E /Y /EXCLUDE:C:\Users\Toni\Downloads\Test\excludedfileslist.txt C:\Users\Toni\Downloads\Downloads\*.* C:\Users\Toni\Downloads\Sonstiges
goto err
:err
if errorlevel 1 ( dir /arashd >> "C:\Users\Toni\Downloads\Test\somefile.txt" 2>&1 ) else ( del /[!*.part] * )
goto end
:end
start /B C:\Users\Toni\Downloads\Test\run.cmd
exit
However, I do not want to move files that are in the process of downloading (ie. I don't want to move partial files with a .part extension).
I tried using an argument to the del command like so:
del /[!*.part] *
but it doesn't seem to work.
How can I avoid moving partial files with the .part extension?
I would probably look at the file extension (using "substitution of FOR variables").
SET "TARGET_DIR=C:\Users\Toni\Downloads\Downloads"
FOR /F "delims=" %%f IN ('dir /b "%TARGET_DIR%"') DO (
REM Ensure it doesn't have '.part' as an extension.
IF NOT "%%~xf"==".part" (
REM Ensure there's not a corresponding ".part" file.
IF NOT EXIST "%TARGET_DIR%\%%~f.part" (
DEL "%TARGET_DIR%\%%~f"
)
)
)
This will delete any file in TARGET_DIR that doesn't have ".part" as a filename extension or have a corresponding ".part" file. (In my experience downloaders that do the ".part" thing also reserve the name of the "finished" file as well, which you'd probably not want to delete.)
Another possible solution (shorter than #mojo's one):
#echo off
cd /d C:\Users\Toni\Downloads\Downloads
attrib +h *.part
for /f "delims=" %%A IN ('dir /b /A:-H') do del %%A
attrib -h *.part
This, will hide all .part files, delete all other files and remove again the hidden attribute.
I've been trying to figure this out for some time now, and I have been searching the web immensely, but I couldn't find the right answer just yet.
So here's my problem:
I want to create a batch file, that searches through all subfolders of a certain directory, finds a specific file and then deletes everything but that file in the folder that the searched file was in.
What I came up with so far is this:
cmd /k for /f %%a IN ('dir /b /s Neuer') do if not [%%a] == [index.txt] del /q %%a
But that deletes just every file in every subfolder - not quite what I want.
Can anyone help?
#echo off
setlocal
if "%~2" == "" (
echo/Usage: %~nx0 ^<directory^> ^<file^>
echo/
echo/%~nx0 will search the given ^<directory^> and its subdirectories
echo/looking for ^<file^>. If the ^<file^> is found, then all the other
echo/files and subdirectories in the same directory as ^<file^> will be
echo/deleted. If more than one ^<file^> is found then this action is
echo/repeated for all matches. Wildcards are not accepted; ^<file^> can
echo/be the name of either a file or a directory.
exit /b
)
if not exist "%~1\" (
echo/%nx0: "%~1" does not exist or is not a directory
exit /b
)
set "TARGETNAME=%~2"
for /r "%~1" %%t in (*) do call :checkFile "%%~t"
for /r "%~1" %%t in (.) do call :checkDir "%%~t"
exit /b
:checkFile
if not "%~nx1" == "%TARGETNAME%" exit /b
echo/* Found "%~1"
echo/ - Deleting files in directory "%~dp1" . . .
for %%f in ("%~dp1*") do call :delFile "%%f"
echo/ - Deleting directories in directory "%~dp1" . . .
for /d %%d in ("%~dp1*") do call :delDir "%%d"
exit /b
:checkDir
set "TESTNAME=%~1"
call :checkFile "%TESTNAME:~0,-2%"
exit /b
:delFile
if "%~nx1" == "%TARGETNAME%" exit /b
echo/ : del "%~1"
rem del "%~1"
exit /b
:delDir
if "%~nx1" == "%TARGETNAME%" exit /b
echo/ : rd /q /s "%~1"
rem rd /q /s "%~1"
exit /b
Notes:
In production one would of course do some error checking.
Maybe some files cannot be deleted because they have the readonly attribute, or the user running the script does not have the appropriate privileges, or they are in use, etc.
Maybe some directories cannot be deleted, for similar reasons, or because they contain hidden files, or because they contain files which cannot be deleted.
The script looks for both files and directories with the given name; it is easy to see how to limit the search to files only.
The script will do its work for all files or directories matching the given name.
As illustrated here the script does not actually delete anything, it just prints what would be deleted. To make it actually do the deletion just remove the rem in front of del and rd.
Exactly for this kind of issues, the command forfiles has been invented:
ForFiles explanation
I want to write a batch file that creates a folder (if it does not exist) and copies a certain file into that folder. So far so good.
The problem is that one folder in the path varies slightly from time to time, so a wildcard becomes necessary.
The following code works just fine but obviously misses to create the folder (Reports). So if the folder is not there, it simply does nothing.
for /r "c:\Users\%USERNAME%\AppData\Local\Packages" &&G in ("LocalState\acn\Reports") do #if exist %%G xcopy /s /i /y c:\temp\Reporting "%%G"
The full path is:
c:\Users\FSchneider\AppData\Local\Packages\“WILDCARD"\LocalState\acn\Reports\
Any idea?
Add /d switch in for to indicate you're looking for a directory, not a file
Add * and omit quotes in the wildcard to indicate it's actually a wildcard
No need for if exist now
for /d /r "%LocalAppData%\Packages" %%G in (LocalState\acn.*) do xcopy /s /i /y c:\temp\Reporting "%%G\Reports"
Next script could help.
#ECHO OFF
SETLOCAL enableextensions
set "_fldrtop=%USERPROFILE%\AppData\Local\Packages"
set "_fldrsub=LocalState\acn"
if not "%~1"=="" set "_fldrsub=%~1" :: my testing data, remove this line
set "_fldrlow=Reports"
if not "%~2"=="" set "_fldrlow=%~2" :: my testing data, remove this line
for /F "delims=" %%G in ('dir /B /AD "%_fldrtop%"') do (
if exist "%_fldrtop%\%%G\%_fldrsub%\" (
if exist "%_fldrtop%\%%G\%_fldrsub%\%_fldrlow%\" (
echo echo "%_fldrtop%\%%G\%_fldrsub%\%_fldrlow%\"
) else (
echo md "%_fldrtop%\%%G\%_fldrsub%\%_fldrlow%\"
)
rem echo xcopy /s /i /y c:\temp\Reporting "%_fldrtop%\%%G\%_fldrsub%\%_fldrlow%\"
)
)
Output:
==>D:\bat\SO\31672436.bat
==>D:\bat\SO\31672436.bat "LocalState\Cache"
md "C:\Users\UName\AppData\Local\Packages\winstore_cw5\LocalState\Cache\Reports\"
==>D:\bat\SO\31672436.bat "LocalState\Cache" 2
echo "C:\Users\UName\AppData\Local\Packages\winstore_cw5\LocalState\Cache\2\"
My working batch file scans a long list of remote servers, copies anything there to a local server, checks the log file for a keyword, and if the keyword is found sends an email. I noticed it is always sending emails, even with a blank log file.
I discovered both FOR loops are using the %1 variable for their output - as seen in ECHO %1 and each line of the called :servermove. For lack of a better explanation it is not resetting %1 to null between loops.
I reviewed almost a dozen SO posts and am somewhat confident using SETLOCAL ENABLEDELAYEDEXPANSION would resolve this. That is where my understanding ends and I am unsuccessful thus far.
Here is the relevant code:
SET DATE=%date:~4,2%-%date:~7,2%-%date:~10,4%
SET HH=%time:~0,2%
SET MN=%time:~3,2%
SET TSTAMP=Time Run is %HH%%MN%
SET DATETIME=%DATE% at %HH%%MN%
SET LOGFILE="\\nt980a3\CreditFileImagesTransmission\LogFiles\%DATETIME%-File Move Log.txt"
SET MailDst=
SET MailSrc=
SET MailSrcName=Center to LDSD File Mover
SET OKMailSub=A Branch Has Sent You Some Files
ECHO %DATETIME% > %LOGFILE%
ECHO. >> %LOGFILE%
FOR /F "tokens=1" %%A IN (%~dp0SourceServers.txt) DO CALL :ServerMove %%A
:cleanuplogs
PUSHD "\\nt980a3\CreditFileImagesTransmission\LogFiles" &&(
FORFILES /S /M *.txt /D -45 /C "CMD /C DEL /Q #path"
) & POPD
:mailtest
FOR /F "tokens=*" %%A IN (%LOGFILE%) DO CALL :searchlog "%%A"
:searchlog
ECHO %1 | find "\\nt">NUL
IF NOT ERRORLEVEL 1 GOTO successmail
GOTO exit
:successmail
IF EXIST %temp%\to.txt DEL %temp%\to.txt
FOR %%a IN (%MailDst%) DO ECHO %%a>>%temp%\to.txt
"%~dp0sendmail.exe" /TO=%temp%\to.txt /FROM=%MailSrcName% ^<%MailSrc%^> /REF=%OKMailSub% /MESSAGE=%LOGFILE% /HOST=
:exit
EXIT
:ServerMove
DIR /S /B \\%1\CreditFileImagesTransmission\*.* >> %LOGFILE%
XCOPY /E /C /I /Y "\\%1\CreditFileImagesTransmission\*.*" "\\nt980a3\CreditFileImagesTransmission\%DATE%\%HH%%MN%\"
FOR /D %%P IN ("\\%1\CreditFileImagesTransmission\*.*") DO RMDIR "%%P" /Q /S
DEL /Q /S "\\%1\CreditFileImagesTransmission\*.*"
I tried changing :mailtest to use %%B in both instances but that also fails. Placing SETLOCAL ENABLEDELAYEDEXPANSION and its counterpart ENDLOCAL before one or the other loop and changing the %%A to !A! does not work either.
Would someone kindly point out the error in my ways and offer suggestions or resources that will help me resolve this?
%1 is the first parameter provided to the procedure - either from the command-line (in the main procedure) or the parameter following the procedure name in call :procedurename parameter1.
In your case, %1 to :servermove is an entry from SourceServers.txt and %1 to :searchlog is each line from %LOGFILE%.
Since you've censored your batch, what you've posted makes little sense. For instance, the :searchlogs routine will take the first line from %LOGFILE% and go to successmail or cleanlogs depending on whether that first line contains the target string \\nt. What it does from there, we can't tell.
We're faced with an XY problem - trying to fix a solution, not a problem.
First problem: Don't use date as a user-variable. It's a "magic variable" which contains the date but it's overridden by a specific set statement.
Having run :servermove for each entry in SourceServers.txt, you are
- accumulating a directory list from \CreditFileImagesTransmission\*.* on that server.
- copying those files to server nt980a3 with a date/timestamp but not including the source-servername so any duplicate name anywhere will overwrite an earlier version. I suggest you include %1 into your destination-name.
- deleting subdirectories
- deleting files.
I'd suggest you simply remove the directory \\%1\CreditFileImagesTransmission\, then re-create it.
I'd also suggest that you add an extra line
goto :eof
after the del /q /s... line. This will cause execution to be transferred to the end-of-file (the colon in :eof is required) and may seem superfluous, but it ensures that the routine has a defined endpoint - if you add a further routine, there is no way the :servermove routine will continue into your new code.
After each server has been processed, you proceed to the :cleanuplogs routine, which I presume deletes logs older than 45 days.
Your next statement is a real problem. What it will do is grab the very first line of the logfile (which contains "%DATE% at %HH%%MN%" with the date resolved as you've set at the start and it then processes this line in :searchlog; there is no \\nt in this line, so errorlevel is set to 1, and the batch proceeds to :EXIT (not a good label in my view, since it's a keyword); executes an exitand should terminate the batch.
This appears not to be what it is actually doing, and I'm at a loss to explain why.
I'd suggest changing
:mailtest
FOR /F "tokens=*" %%A IN (%LOGFILE%) DO CALL :searchlog "%%A"
:searchlog
ECHO %1 | find "\\nt">NUL
IF NOT ERRORLEVEL 1 GOTO successmail
GOTO exit
to
:mailtest
find "\\nt" %LOGFILE%>NUL
IF NOT ERRORLEVEL 1 GOTO successmail
:failmail
echo "\\nt" was found in the log
pause
GOTO exit
but I can't test that...
:mailtest
FOR /F "tokens=*" %%A IN (%LOGFILE%) DO CALL :searchlog "%%A"
You are missing a GOTO :EOF or similar goto here because it will drop through to the routine below once the above is finished.
:searchlog
ECHO %1 | find "\\nt">NUL
IF NOT ERRORLEVEL 1 GOTO successmail
GOTO exit
I feel you can not carry the %1 of first for loop to others. Try to transfer that to another variable like below.
:ServerMove
set servername=%1
DIR /S /B \\%servername%\CreditFileImagesTransmission\*.* >> %LOGFILE%
XCOPY /E /C /I /Y "\\%servername%\CreditFileImagesTransmission\*.*" "\\nt980a3\CreditFileImagesTransmission\%DATE%\%HH%%MN%\"
FOR /D %%P IN ("\\%servername%\CreditFileImagesTransmission\*.*") DO RMDIR "%%P" /Q /S
DEL /Q /S "\\%servername%\CreditFileImagesTransmission\*.*"
Cheers, G
I use this script to clean history, cookies and cache (Temporary Internet Files) for all users AND it should also clean the temp dir BUT there seems to be something wrong.
Two things get mixed up I think, the %temp% variable (= D:\TEMP in my environment)
AND the users temp dir in the %userprofile%.
:: Works on Win XP -and- on Win 7
#echo off
Set "RegKey=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
set "regkey2=HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\shell folders"
call:getspecialfolders "Cache, History, Cookies"
For /f "tokens=*" %%? in (
'Reg.exe QUERY "%RegKey%" ^|findstr /ric:"\S-1-5-21-[0-9]*-[0-9]*-[0-9]*-[0-9]*$"'
) do (
For /f "tokens=2,*" %%A in (
'Reg.exe QUERY "%%?" /v ProfileImagePath ^|find /i "ProfileImagePath"'
) do call:Go %%B
)
start ""/w "%windir%\system32\RunDll32.exe" InetCpl.cpl,ClearMyTracksByProcess 255
:end ***
goto:EOF
:Go
call Set "Target=%*"
If EXIST "%Target%" call:Clear "%Target%"
exit /b 0
:Clear
REM echo.&echo.%~1\%$$Cache%
pushD "%~1\%$$Cache%" &&(
rmdir /S /Q .
popD)2>C:\test1_TEMP_IE.txt
REM echo.&echo.%~1\%$$History%\History.IE5
REM pushD "%~1\%$$History%\History.IE5" &&(
REM rmdir /S /Q .
REM popD)2>C:\test1_History_IE.txt
REM echo.&echo.%~1\%$$History%
pushD "%~1\%$$History%" &&(
rmdir /S /Q .
popD)2>C:\test1_History.txt
REM echo.&echo.%~1\%$$Cookies%
pushD "%~1\%$$Cookies%" &&(
rmdir /S /Q .
popD)2>C:\test1_Cookies.txt
ECHO.&echo.%~1\%$$temp%
pushD "%~1\%$$temp%" &&(
rmdir /S /Q .
popD)2>C:\test1_Temp.txt
exit /b 0
:getspecialfolders
Set "FoldersToClear=%~1"
For %%* in (%FoldersToClear%) Do (
For /f "tokens=2,*" %%A in (
'reg.exe query "%regkey2%" /v %%* ^|find /i "%%~*"'
) do Call:sf1 "%%~B" "%%~*"
)
Call:sf2 "%temp%" "temp" "%userprofile%"
exit /b 0
:sf1
Call set "sf=%~1"
Call set "$$%~2=%%sf:%userprofile%\=%%"
exit /b 0
:sf2
Call set "sf=%~1"
call Set "usr=%~dpns3"
Call set "$$%~2=%%sf:%usr%\=%%"
exit /b 0
BUT somehow I can't get the last "temp part" to function so it cleans the %temp% (D:\Temp in my environment) and to also find al "temp dir's" in the %userprofile%.
ie. this for instance does work for %temp%:
PushD "%Temp%" && (
ATTRIB -S -H -R -A /D /S & (
For /f "Tokens=*" %%* in ('dir "%Temp%" /B') Do (
RD "%Temp%\%%*" /S /Q || Del /F /S /Q "%Temp%\%%*"))&PopD)2>c:\test0b_TEMP.txt
and this ie. work for the "user(s) temp":
::Set Search directory to "Documents and Settings" folder
(Set Target=%AllUsersProfile:~0,-10%)
title,Finding the Temp subfolders in %Target%&COLOR 9E
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd/D "%target%\%%*\Local Settings\Temp" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
)
I hope some one can help me out fixing the script, I think it's in the :sf2 and/or in combination with the %temp% part, somehow 2 things get mixed-up now ("users temp" en "environment temp").
All right, this time I think there is a way to fix this, namely, by adding a check whether the variable contains a relative or an absolute path, directly before proceeding with the cleanup. The idea is to test for the presence of the colon (:) in the string. If the colon is present then the path could not be converted to a relative path previously and so should be used as is, without pre-pending the profile path, otherwise the profile path should be attached before going on.
Here's a basic example that you can test and play with, if you like:
#ECHO OFF
SET somepath=D:\TEMP
CALL :checkpath
SET "somepath=Local Settings\Temp"
CALL :checkpath
PAUSE
GOTO :EOF
:checkpath
IF "%somepath%"=="%somepath:*:=%" (ECHO Relative path) ELSE ECHO (Absolute path)
In your particular situation I would probably apply the method like this:
instead of
…
ECHO.&echo.%~1\%$$temp%
pushD "%~1\%$$temp%" &&(
rmdir /S /Q .
popD)2>C:\test1_Temp.txt
…
I would try
…
IF "%$$temp%"=="%$$temp:*:=%" (SET "tmppath=%~1\%$$temp%") ELSE SET "tmppath=%$$temp%"
ECHO.&echo.%tmppath%
pushD "%tmppath%" &&(
rmdir /S /Q .
popD)2>C:\test1_Temp.txt
…
As you can see, a temporary variable is used to store the actual path to be processed. I understand it is enough to replace only the part where the temporary folder is being cleared, but you can see that the method can be easily applied to other folders as well, if needed.
It seems like your sf2 subroutine is trying to get a relative path of the Temp folder by cutting off the beginning of the path, which is essentially the user profile path:
Call set "$$%~2=%%sf:%usr%\=%%"
where sf contains the Temp folder and usr the user profile. So instead of, for instance, C:\Documents and Settings\APOC\Local Settings\Temp you would get simply Local Settings\Temp.
But there's a problem. Though the sf variable is assigned with the proper path, the usr variable, on the other hand, for some reason is assigned with the short named variant of the user profile path. That is, instead of something like C:\Documents and Settings\APOC it receives something like C:\DOCUME~1\APOC. Here's the offending line:
call Set "usr=%~dpns3"
So, when the formerly quoted line is executed, the expected substitution never happens, because C:\Documents and Settings\APOC doesn't match C:\DOCUME~1\APOC, naturally. As a result, the $$temp variable ends up with the complete path instead of the relative path, and because of that, the relevant parts of your code that reference $$temp don't do their job as expected.
In short, I think you don't need that sf2 routine at all. The sf1 routine seems to do just the same as sf2, only with a different set of parameters to pass. So, instead of
Call:sf2 "%temp%" "temp" "%userprofile%"
I'd suggest you to try this:
Call:sf1 "%temp%" "temp"
I changed the line for temp a little, is this a correct way? (it does work but is it properly formated?)
IF "%$$temp%"=="%$$temp:*:=%" (SET "tmppath=%~1\%$$temp%") ELSE SET "tmppath=%$$temp%"
ECHO.&echo.%tmppath%
pushD "%tmppath%" &&(
ATTRIB -S -H -R -A /D /S & (
rmdir /S /Q . || Del /F /S /Q .
)&popD)2>C:\test1_Temp.txt
+Extra "Del /f /s /q" for possible hard/read-only files (and additional attrib)
By the way
There still seems something not going 100% in the script with the "temp"-part, I changed my default temp settings in windows to the default paths voor testing purposes and I get these 3 error's:
screenshot of the error | url: http://img199.imageshack.us/img199/9127/errorif.jpg
script run with the windows default temp-path's:
[user] %UserProfile%\Local Settings\Temp and [system] %SystemRoot%\Temp
I'm not sure why I get these error's, when I set both temp parameters to D:\TEMP, I get 3 times the same sort of error but than for D:\TEMP instead of available/active users \local settings\Temp. Perhaps the problem is in locals~1???
(The temp-directories do get cleaned though, but why does it say it can't find the path?)