Introduction
The are times when you need a list of all the files that are checked out right now from TFS. Visual Studio does provide a search by status window (File -> Source Control -> Find), but what if all that you need is a text file with the names of files that you checked out? This is where TF.exe comes to the rescue. The purpose of this executable is to provide command line capabilities to all the TFS operations that you already do with Visual Studio and Source Control Explorer.
In most cases, a TFS directory is mapped to one folder, so you get a one-to-one mapping. This is the prerequisite for this batch script. For the purpose of this article, I'm going to use TFS directory $/Projects/UserName/MyApp which is mapped to a local folder C:\Users\UserName\Documents\Visual Studio\Projects\MyApp. Obviously, you're going to have to change these settings to your own mappings. The TF.exe version that the script uses is the VS 2012 version so change it at your convenience.
To retrieve a list of changed files, the script executes the Status command. For each line, it tries to determine if the line contains the local folder, which was defined at the start of the script. If so, it extracts the full file path and relative file path. As it is, the script outputs the relative paths to the output file. The line of code for printing the full path is remarked, so if you need that and not the other, just switch the remarks on these lines of code. You can remove the redirections to outputFile
if you just need to print the files to command line.
@echo off
setlocal EnableDelayedExpansion
set "folder=C:\Users\UserName\Documents\Visual Studio\Projects\MyApp\"
set "itemspec=$/Projects/UserName/MyApp/"
set "workspace=WorkspaceName"
set "tf=C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\TF.exe"
set "outputFile=outputFile.txt"
type nul>%outputFile%
call :strlen "%folder%", folderLength
if %folderLength% equ 0 goto :eof
set cmd="%tf%" stat %itemspec% /workspace:%workspace% /format:brief /recursive
for /f "delims=" %%G in ('%cmd%') do (
set "line=%%G"
call :strlen "!line!", lineLength
if !lineLength! gtr 0 call :printFile %line%, !lineLength!, %folder%, %folderLength%, %outputFile%
)
goto :eof
::printFile(line, lineLength, folder, folderLength, outputFile)
:printFile
setlocal
set /a "lineLength -= folderLength"
if %lineLength% lss 0 endlocal & goto :eof
for /l %%i in (0,1,%lineLength%) do (
call set "sub=%%line:~%%i,%folderLength%%%"
if %folder% == !sub! (
call set "fullPath=%%line:~%%i%%"
set /a "index=%%i + folderLength"
call set "relPath=%%line:~!index!%%"
echo !relPath!>>%outputFile%
::echo !fullPath!>>%outputFile%
endlocal
goto :eof
)
)
endlocal
goto :eof
::strlen(string, out length)
:strlen
setlocal
set "length=0"
set "#=%~1"
:strlenLoop
if defined # (set "#=%#:~1%" & set /a "length += 1" & goto strlenLoop)
endlocal & set "%~2=%length%"
goto :eof