remove space from @PATH or how to not remove everything due extra space in the end

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
romashkaz
Posts: 1
Joined: 25 Mar 2020 03:52

remove space from @PATH or how to not remove everything due extra space in the end

#1 Post by romashkaz » 25 Mar 2020 04:01

I have such script which removes old files locally from my computer and it works for some time until I get some directory created with extra space, something like "test_directory " and after that the script removed all the files from disk C. Could you please help me somehow to envelope @PATH to avoid extra space ( it seems that extra space calls as an additional parameter ) or maybe I can just check for an empty spaces before? I'm not so good in dos scripting and very hope for your help.

Script looks like:

Code: Select all

@ECHO OFF
SET KEEP_DAYS=7
SET KEEP_2WEEKS=14
SET KEEP_1YEAR=365

SET ROOT_DIR=C:\Users\test\Desktop\tickets\BAT_TEST\test_directory
SET EXCLUDE_DIR=archive
SET DIR_2WEEKS=\archive\keep-two-weeks
SET DIR_1YEAR=\archive\keep-one-year

SET LOG_FILE=C:\Users\test\Desktop\tickets\BAT_TEST\cleanup.log

IF NOT "%1"=="-D" (
	ECHO Specify -D parameter to confirm deletion start
	GOTO :EOF
)
IF %KEEP_DAYS% LSS 7 (
	ECHO KEEP_DAYS value %KEEP_DAYS% is too small!
	GOTO :EOF
)

ECHO Deleting files older than %KEEP_DAYS% day(s). >> %LOG_FILE%
ECHO Start %date:~-11% %time% >> %CD%\%date:~-11%log >> %LOG_FILE%

SET /A COUNT=1

for /D %%E in (%ROOT_DIR%\*) do (
	ECHO Processing %%E >> %LOG_FILE%

	for /D %%D in (%%E\*) do ECHO %%D | findstr /v /c:"%EXCLUDE_DIR%" >> %LOG_FILE% && call :deleteFiles %%D
	
	ECHO Deleting files in archive folders. >> %LOG_FILE%
	if exist %%E%DIR_2WEEKS% call :deleteArchive %%E%DIR_2WEEKS% %KEEP_2WEEKS%
	if exist %%E%DIR_1YEAR% call :deleteArchive %%E%DIR_1YEAR% %KEEP_1YEAR%
	
	ECHO Finished %%E >> %LOG_FILE%	
)
GOTO :DONE

:deleteFiles
FORFILES /p %1 /S /M * /C "CMD /C  if @isdir==FALSE del /F /Q @PATH && echo @PATH @FSIZE @FDATE" /D -%KEEP_DAYS% >> %LOG_FILE%
GOTO :EOF

:deleteArchive
FORFILES /p %1 /S /M * /C "CMD /C del /F /Q @PATH && echo @PATH @FSIZE @FDATE" /D -%2 >> %LOG_FILE%
GOTO :EOF

:DONE
::ECHO Total files deleted %COUNT% >> %LOG_FILE%
ECHO Stop  %date:~-11% %time% >> %LOG_FILE%
My suggestion is that the problem is in ":deleteFiles" and ":deleteArchive" where we are processing @PATH with extra space, but at this moment I'm not so experienced in this language. Could you please help me or suggest something? Thanks!

penpen
Expert
Posts: 1786
Joined: 23 Jun 2013 06:15
Location: Germany

Re: remove space from @PATH or how to not remove everything due extra space in the end

#2 Post by penpen » 28 Mar 2020 18:33

If i understand you right, then i doubt that the main issues with your script are related the "@PATH" parts.
Whenever your outer loop (using for-variable %%E) is assigned a directory name with an axtra space (at the end),
your inner loop (using for-variable %%D) won't process the directory you want it to process:
It will process two directories divided by that extra space character.

Example (using your above example, if i read it right):
"%%~E" is set to "C:\Users\test\Desktop\tickets\BAT_TEST\test_directory\test_directory "

Code: Select all

:: Then the following line
for /D %%D in (%%E\*) do ...

:: will be executed using the above value for %%E, so it ends up executing:
for /D %%D in (C:\Users\test\Desktop\tickets\BAT_TEST\test_directory\test_directory \*) do ...
So it now tries to process the directories "C:\Users\test\Desktop\tickets\BAT_TEST\test_directory\test_directory" and "\*".

To fix such a behaviour, just encapsulate file names in doublequotes whenever you are using them,
which is also recommended when assigning values to environment-variables
(also you should enable extensions in case your admin has changed the default setting for that):

Code: Select all

@ECHO OFF
setlocal enableExtensions disableDelayedExpansion
SET "KEEP_DAYS=7"
...
SET "ROOT_DIR=C:\Users\test\Desktop\tickets\BAT_TEST\test_directory"
...
for /D %%E in ("%ROOT_DIR%\*") do (
...
	for /D %%D in ("%%E\*") do ECHO "%%D" ...
...
	if exist "%%E%DIR_2WEEKS%" call :deleteArchive "%%E%DIR_2WEEKS% %KEEP_2WEEKS%"
...
Also i personally prefer to position redirections in front of the command and use "(" to seperate the echo-command from its parameter:

Code: Select all

>> "%LOG_FILE%" echo(Deleting files older than %KEEP_DAYS% day(s).
I also suggest, you should first replace the functions ":deleteFiles" and ":deleteArchive" by simply the following and see if the produced call matches your expectations:

Code: Select all

:deleteFiles
echo(Processing :deleteFiles "%~1"
GOTO :EOF

:deleteArchive
echo(Processing :deleteArchive "%~1"
GOTO :EOF
After that use forfile commands that just echo what you want to do ('echo(del ...'), and only at last remove that echo and run a test on a sample (on a secure system), before using the final script.


penpen

Post Reply