I'm trying to install an app from my PC running Windows 10 using adb and I need to use command cd
before I'm installing the app.
But I see a strange behavior. If I use the cd
command before the if
statement, it's working well. But if I use the cd
command inside the if
statement, it is not working.
Here is what I tried:
This one is working well:
cd %~f0\..\..\apps\app_sample\samples\sample_app\build\outputs\apk
if "%arg1%" == "aaa" (
adb install %CD%\sample_app-debug.apk
)
This one results on execution in an error:
if "%arg1%" == "aaa" (
cd %~f0\..\..\apps\app_sample\samples\sample_app\build\outputs\apk
adb install %CD%\sample_app-debug.apk
)
The error output is:
Failed to stat
C:\Users\ntuser\Documents\workspace\Team\script\sample_app-debug.apk:
No such file or directory
It looks like it did not do the cd
command in this case.
Whenever Windows command interpreter cmd.exe
encounters the beginning of a command block starting with (
and ending with matching )
, the entire block is preprocessed before the command left to the command block is executed at all. This means all environment variables using %variable%
syntax are replaced by current value of the referenced environment variable before executing the command which later executes the entire command block. This behavior can be seen on running a batch file from within a command prompt window without @echo off
being usually at top of the batch file.
This means on your batch file with the IF command and the command block to execute on condition being true that %CD%
is replaced by current directory before the command IF is executed and so also before the command CD is executed at all.
There are two possibilities:
- explicitly enable delayed environment variable expansion and reference the environment variable in the command block with using syntax
!variable!
or
- don't use a command block by using GOTO or a subroutine and CALL.
Solution 1 with enabled delayed environment variable expansion:
setlocal EnableDelayedExpansion
if "%arg1%" == "aaa" (
cd "%~dp0..\apps\app_sample\samples\sample_app\build\outputs\apk"
adb.exe install "!CD!\sample_app-debug.apk"
)
endlocal
Solution 2 with not using a command block at all and instead use GOTO:
if "%arg1%" == "aaa" goto AAA
rem Other commands
goto :EOF
:AAA
cd "%~dp0..\apps\app_sample\samples\sample_app\build\outputs\apk"
adb.exe install "%CD%\sample_app-debug.apk"
goto :EOF
rem Or use a different GOTO to continue processing somewhere else in batch file.
Another solution 2 is using a subroutine and command CALL:
if "%arg1%" == "aaa" call :AAA
rem Other commands executed even if above condition is true.
rem Avoid a fall through to the subroutine below.
goto :EOF
:AAA
cd "%~dp0..\apps\app_sample\samples\sample_app\build\outputs\apk"
adb.exe install "%CD%\sample_app-debug.apk"
rem Exit the subroutine and continue on line below calling it.
goto :EOF
But I think your code can be even more easier because it is most likely not necessary to specify the *.apk file with full path.
if "%arg1%" == "aaa" (
cd "%~dp0..\apps\app_sample\samples\sample_app\build\outputs\apk"
adb.exe install sample_app-debug.apk
)
And perhaps also working is:
if "%arg1%" == "aaa" adb.exe install "%~dp0..\apps\app_sample\samples\sample_app\build\outputs\apk\sample_app-debug.apk"
It is better to use here %~dp0
which references the drive and path of the batch file ending with a backslash instead of %~f0
which is the name of the batch file with file extension and full path.
For example with batch file being C:\Temp\Test\Install.bat
the command line
cd "%~f0\..\..\apps\app_sample\samples\sample_app\build\outputs\apk"
results in execution of
cd "C:\Temp\Test\Install.bat\..\..\apps\app_sample\samples\sample_app\build\outputs\apk"
and the current directory is C:\Temp\apps\app_sample\samples\sample_app\build\outputs\apk
after this command with in real invalid directory name Install.bat
in path which is not a directory.
The command line
cd "%~dp0..\apps\app_sample\samples\sample_app\build\outputs\apk"
is much better as it results in execution of
cd "C:\Temp\Test\..\apps\app_sample\samples\sample_app\build\outputs\apk"
which makes also C:\Temp\apps\app_sample\samples\sample_app\build\outputs\apk
the current directory, but with a completely correct path in comparison to above cd
command line.
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.
call /?
... explains %~dp0
and %~f0
.
cd /?
endlocal /?
goto /?
if /?
rem /?
set /?
... explains delayed environment variable expansion on an IF and a FOR example.
setlocal /?
I don't have adb installed. So I can only assume that it is an executable with file extension .exe
and not a batch file with file extension .bat
or .cmd
which would require the usage of call adb.bat ...
or call adb.cmd ...
in this batch file.