xp_cmdshell in a transaction I need to run multiple scripts in a certain folder in a transaction and rollback if there are any errors. At this point I'm just trying to get the rollback to work without a try catch.

Currently when I run the script, it gets the proper list of sql files recursively, but does not rollback the changes if there is an error. If there are 10 files and 3 complete but there is an error on the 4th, the first 3 files do not rollback.

Here is my script:

BEGIN TRANSACTION

CREATE TABLE ##SQLFiles ( SQLFileName VARCHAR(2000))
GO

DECLARE @folderPath VARCHAR(100) = 'folder\path' 
DECLARE @cmd VARCHAR(8000) = 'dir /b /s "' + @folderPath + '\*.sql"'

INSERT INTO ##SQLFiles
EXECUTE master.dbo.xp_cmdshell @cmd
GO 

DECLARE cFiles CURSOR LOCAL FOR
    SELECT DISTINCT
        [SQLFileName]
    FROM ##SQLFiles
    WHERE [SQLFileName] IS NOT NULL AND
          [SQLFileName] != 'NULL'
    ORDER BY [SQLFileName]

DECLARE @folderPath         VARCHAR(100) = 'folder\path' 
DECLARE @vFileName          VARCHAR(200)
DECLARE @vSQLStmt           VARCHAR(4000)

SELECT * FROM ##SQLFiles

OPEN cFiles
FETCH NEXT FROM cFiles INTO @vFileName
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @vSQLStmt = 'master.dbo.xp_cmdshell ''osql -S ServerName -U UserName -P "password" -d dbname -i "' + @folderPath + @vFileName + '"'''
    PRINT @vSQLStmt
    EXECUTE (@vSQLStmt)

    FETCH NEXT FROM cFiles INTO @vFileName
END

CLOSE cFiles
DEALLOCATE cFiles
GO

DROP TABLE ##SQLFiles
GO

ROLLBACK TRANSACTION


Is there any way to get the changes made by the files to be rolled back?
No, absolutely impossible. Each sqlcmd invocation is a different session and transaction cannot span sessions.

Your use of a transaction on the script that invokes the sqlcmd is completely useless, it has nothing to do with the scripts being run.