You have a standard DELAYED EXPANSION problem, discussed endlessly on SO.
When batch encounters a "Block statement" - that is typically a parenthesised statement spread over many lines such as your IF EXIST then the entire statement is parsed through to the closing parenthesis AND at this time, ANY %var% is replaced by the value of that variable as it stands WHEN THE STATEMENT IS PARSED
Consequently, your ECHO %olddirectory% is replaced by ECHO since olddirectory has no value AT PARSE TIME and executing ECHO will report ECHO is On/Off progdata on the other hand IS set at parse-time and hence echo Found %progdata% is replaced by echo Found C:\ProgramData
The very simplest cure is to move the ECHO statement outside of the block
IF EXIST "%progdata%" (
echo Found %progdata%
SET oldDirectory="%progdata%\%datetime%"
)
echo Olddirectory=%oldDirectory%
(I added the olddirectory= so that the echo statement finds something to echo if olddirectory is not set)
The second easiest way to display the value is
IF EXIST "%progdata%" (
echo Found %progdata%
SET oldDirectory="%progdata%\%datetime%"
CALL echo %%oldDirectory%%
)
Here, the ECHO command is not expanded in the context of the IF, but in the context of the CALL which acquires its environment from the run-time value of the IF context.
The third easiest way to display the value is by using the delayedexpansion option of a setlocal command. An NT batch command traditionally starts
@echo off
setlocal
which suppresses echoing and establishes a local environment. Any changes to the local environment are backed out when an endlocal or end-of-file is reached in the setlocal's context. If this mantra is consistently followed, we don't get the situation where a variable is established by one batch and the environment is 'dirty' for the next. Consider running your original twice within the same cmd session. progdata, and all of the other variables you are establishing would remain set for the second coming - and hence olddirectory may be set by your first invocation, and retain that stale data if for some reason it's not EXPLICITLY set in the second. setlocal backs all those changes out for you.
setlocal enabledelayedexpansion adds an extra facility to the mix. Whereas %var% is resolved to the PARSE-TIME value of var, if delayedexpansion has been invoked then !var! is resolved to the RUN-TIME value - as it changes in a FOR loop...
Hence, adding
SETLOCAL ENABLEDELAYEDEXPANSION
at a strategic point (after the @echo off until you're off your training wheels...) would allow you to make a simple change to the display of olddirectory
IF EXIST "%progdata%" (
echo Found %progdata%
SET oldDirectory="%progdata%\%datetime%"
echo !oldDirectory!
)