Close game addons when the game closes - powershell

I'm playing Path of Exile with a few addons. With the help of this forum I've written a script that starts all the addons and then the game, with a single batch file. Now I'd also like for it to close all the addons when the game closes. I'm open to using PowerShell, I just don't know how. I also don't know how to translate what I've already written into PowerShell. The code is below. Thank you!
#echo off
:: BatchGotAdmin
::-------------------------------------
REM --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
echo Requesting administrative privileges...
goto UACPrompt
) else ( goto gotAdmin )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
set params = %*:"="
echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
del "%temp%\getadmin.vbs"
exit /B
:gotAdmin
pushd "%CD%"
CD /D "%~dp0"
::--------------------------------------
::ENTER YOUR CODE BELOW:
runas /noprofile /user:CARLOSDESKTOP\resur /savecred "C:\Games (C SSD)\PoE\Addons\Exiled Presence v1.0.5\Exiled-Presence.exe"
runas /noprofile /user:CARLOSDESKTOP\resur /savecred "C:\Games (C SSD)\PoE\Addons\poe-overlay\poe-overlay.exe"
cd /d "C:\Games (C SSD)\PoE\Addons\Awakened PoE Trade"
start "" "C:\Games (C SSD)\PoE\Addons\Awakened PoE Trade\Awakened PoE Trade.exe"
cd /d "C:\Games (C SSD)\PoE\Addons\Autoflask"
start "" "C:\Games (C SSD)\PoE\Addons\Autoflask\PoEAutoFlask.ahk"
cd /d "C:\Games (C SSD)\PoE\Addons\POE-Trades-Companion-dev"
start "" "C:\Games (C SSD)\PoE\Addons\POE-Trades-Companion-dev\POE Trades Companion.ahk"
cd /d "C:\Games (C SSD)\PoE"
start "" "C:\Games (C SSD)\PoE\PathOfExile_x64.exe"

Related

Using Batch to copy file attributes (at least Created,LastWrite,LastAccess) from 1 file to a 2nd

I am trying to copy attributes for *.mkv *.mp4 video files. I have found a way to copy file attributes, but it is quite slow as it is calling Powershell to use it commands.
powershell ^(ls '!orig-file!'^).CreationTime = ^(ls '%%I'^).CreationTime
powershell ^(ls '!orig-file!'^).LastWriteTime = ^(ls '%%I'^).LastWriteTime
powershell ^(ls '!orig-file!'^).LastAccessTime = ^(ls '%%I'^).LastAccessTime
...................
%%I equals new-file for each FOR loop iteration
Is there a way to do this faster without Powershell?
Otherwise, I assume it would be possible to only call Powershell once and copy all 3 or more attributes in 1 line? I'am assuming that reading each file attribute individually is the only way to copy, but I would prefer all attributes if there are any more to copy.
EDIT: FULL CODE: (with all remarked/commented lines removed) ( Batch Convert Videos audio from one format to another )
#ECHO OFF
SETlocal
SET drive="~dp0"
SET string=%CD%
SETlocal EnableExtensions EnableDelayedExpansion
SET "drive=G:"
SET ^"Exclude-AlltheseFolders=#snapshot,output^"
SET "Convert_Audio1=Y"
SET "Convert_TO=aac"
SET "Codec1=eac3"
SET "Codec2=flac"
SET "Codec3=dts" &SET "Codec4=pcm_s24le" &SET "Codec5=aac" &SET "Codec6=ac3"
SET "KeepExtraAudio_NoOrig=Y"
SET "KeepOrigAudio=N"
SET "OverWriteFiles=N"
SET "ExtractTime=Y"
SET "time_to_start_from=00:00:10" &SET "duration_to_capture=00:00:15"
SET "TempFilePath=C:\Windows\Temp\ffmpeg-CountingScript-AllFilesInCurrentDirlist%DT%--%HH%.%MM%.%SS%.txt"
IF !ExtractTime! == Y ( SET "FFmpgextractTime= -ss !time_to_start_from! -t !duration_to_capture!")
ECHO THIS IS JMK1
IF !OverWriteFiles! == Y (SET "OverWrite=-y ") ELSE (SET "OverWrite=-n ")
IF !Convert_Audio1! == Y (
IF !Convert_TO! == aac ( set "Convert_TO=libfdk_aac" )
SET "FFmpgConvertStream1=-c:a:0 !Convert_TO! -b:a:0 640k -disposition:a:0 default"
IF !KeepExtraAudio_NoOrig! == Y (
SET "FFmpgXtraStream=-c:a copy"
)
IF !KeepOrigAudio! == Y (
SET "KeepOrigAudio_ffMpg=-map 0:a:0? -c:a:0 copy"
SET "KeepExtraAudio_NoOrig=Y"
)
) ELSE (
SET "ConvertCodecs=1"
SET "KeepOrigAudio_ffMpg=-c:a:0 copy"
SET "KeepExtraAudio_NoOrig=Y"
)
SET "delm1=^\^>" /c:"^\^<"
SET ^"Exclude-Final=/c:"\^<!Exclude-AlltheseFolders!\^>"^"
SET ^"Exclude-Final=!Exclude-Final:,=%delm1%!^"
dir *.mkv *.mp4 /A-D-H /B /S |findstr /R %Exclude-Final% /v /i>%TempFilePath%
Echo: These are the folders being Excluded: "!Exclude-AlltheseFolders!"
SET "FINALCOMMAND="
SETlocal EnableExtensions DisableDelayedExpansion
SET "ProgramFolder=C:\Program Files\FFmpeg-v2020\bin"
SET "ProbeOptions=-v quiet -select_streams a:0 -show_entries "stream^^=codec_name" -of json"
SET "FilesFound=0" & SET "FilesEncoded=0" & SET "output="
for /F "delims=" %%I in (%TempFilePath%) do (
SET "output=%drive%%%~pI%%~nxI" & SET folder=%drive%%%~pI & SET "filename=%%~nxI" & SET /A FilesFound+=1
SETlocal EnableExtensions EnableDelayedExpansion
IF exist "%drive%%%~pIoutput\%%~nxI" (SET "Convert_Audio1=N") ELSE SET "Convert_Audio1=Y"
IF "!Convert_Audio1!" == "Y" (
SET "AudioCodec=" & SET "ConvertCodecs="
for /F "eol={ tokens=1,2 delims=,:[ ]{} " %%B in ('""%ProgramFolder%\ffprobe.exe" %ProbeOptions% "%%I""') do (
IF "%%~B" == "codec_name" (
IF not defined AudioCodec (
SET "AudioCodec=%%~C"
)
IF "%%~C" == "%Codec1%" (SET "ConvertCodecs=1"
) else IF "%%~C" == "%Codec2%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec3%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec4%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec5%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec6%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
)
)
)
)
IF !ConvertCodecs! == 1 (
ECHO [91m==!TIME!================[0m!Codec1! [94min[0m- %%I [91m=========[0m
)
IF !ConvertCodecs! == 1 (
IF /I "!output!" == "%%I" (
SET "output=%~dp0output\!filename!"
MKDIR "%~dp0output\"
) ELSE (
MKDIR "%drive%%%~pI"
)
SET "FINALCOMMAND=ffmpeg !OverWrite!-hide_banner%FFmpgextractTime% -loglevel quiet -hwaccel auto -stats -i "%%I" -map 0:v -map_metadata 0 -movflags use_metadata_tags -map 0:a? -map 0:s:0? -c:s:0 copy -c:v copy %FFmpgXtraStream% %FFmpgConvertStream1% %KeepOrigAudio_ffMpg% "!output!" "
ECHO this is the command1: !FINALCOMMAND!
!FINALCOMMAND!
ECHO [91m=====[0mCOMPLETE[91m===============[0m .
IF not %FilesEncoded% == 0 ECHO This one was a failure. Count Encoded so far: "%FilesEncoded%"
IF not errorlevel 1 SET /A FilesEncoded+=1
powershell ^(ls '!output!'^).CreationTime = ^(ls '%%I'^).CreationTime
powershell ^(ls '!output!'^).LastWriteTime = ^(ls '%%I'^).LastWriteTime
powershell ^(ls '!output!'^).LastAccessTime = ^(ls '%%I'^).LastAccessTime
for /F "delims=" %%p in ("!ConvertCodecs!") do (
ECHO THIS IS P: %%p
ENDLOCAL
SET /A FilesEncoded=%%p+FilesEncoded
)
) ELSE ( ECHO ##NOT PROCESSING##: !TIME! - %%I ## & ECHO [91m=====--[0mFILE ALREADY EXISTS! [91m======================[0m Next File [91m===========================[0m )
)
)
IF %FilesFound% == 1 ( SET "PluralS=" ) else SET "PluralS=s"
ECHO [91m***************************************************************************************[0m
ECHO Re-encoded %FilesEncoded% of %FilesFound% video file%PluralS%.
ECHO [91m***************************************************************************************[0m
endlocal
endlocal
endlocal
exit /b
The following copies the specified attributes using a single
powershell.exe call:
Note the use of gi, a built-in alias of the Get-Item cmdlet.
ls - on Windows - is (unfortunately) a built-in alias of the Get-ChildItem cmdlet (whose use would work here too, and whose PowerShell-idiomatic alias is gci); however, such aliases - named for other shells' / platforms' built-in commands / utilities are best avoided - see the bottom section of this answer for more information.
Enclosing the entire (implied) -Command argument in "..." obviates the need for ^-escaping of individual chars.
powershell "$target = gi '!orig-file!'; $source = gi '%%i'; 'CreationTime', 'LastWriteTime', 'LastAccessTime' | foreach { $target.$_ = $source.$_ }"
Note that the above could still fail in the following cases:
If a file name happens to contain ' itself; if so, use \""...\"" (sic) instead of '...'
See this answer for more information.
If a file name happens to contain [ and ]; if so, use gi -LiteralPath instead of just gi, which implies gi -Path.

Automated FTP transfer using WinSCP and Batch file with Email notification

I am trying to write a batch file that will:
connect to FTP server using WinSCP
use RSA keys to authenticate
try two different keys, in case one fails
send an email notification about fail transfers
save logs
Solution to the question:
#echo off
:: FTP Configuration
SET TRIES=2
SET INTERVAL=10
SET Server=user#server.com
SET HostKey=
SET ProdHostKey=ssh-rsa 2048 KeyKeyKeyKeyKeyKeyKeyKey
SET DRHostKey=ssh-ed25519 256 KeyKeyKeyKeyKeyKeyKeyKey
SET PrivateKey=C:\RSA_Privatekey\Key.ppk
SET Source=/Files/Work/
SET Destination=D:\Inbox\
:: Log File Configuration
SET DateStamp=%date:~-4,4%%date:~-10,2%%date:~-7,2%
SET LogFile=D:\Logs\WinSCP\WinSCP-FTP_%DateStamp%.log
:: Email Configuration
SET SMTPServer=smtp.server.com
SET EmailFrom=%computername%#server.com
SET EmailTo="email1#server.com", "email2#server.com"
SET EmailSubject="FTP Transfer Failure"
SET EmailAttachment="%LogFile%"
SET EmailBody="FTP transfer failed.`r`nLog file attached."
:Begin
SET HostKey=%ProdHostKey%
:Retry
:: Launch WinSCP
"C:\Program Files (x86)\WinSCP\WinSCP.com" ^
/log="%LogFile%" /ini=nul ^
/command ^
"Option confirm off" ^
"open sftp://%Server%/ -hostkey=""%HostKey%"" -privatekey=""%PrivateKey%"" -rawsettings ConsiderDST=0" ^
"Get -delete "%Source%*.*" "%Destination%"" ^
"Close" ^
"Exit"
SET WINSCP_RESULT=%ERRORLEVEL%
if %WINSCP_RESULT% equ 0 (
echo Success
) else (
SET /A TRIES=%TRIES%-1
IF %TRIES% GTR 1 (
echo Transfer failed, retrying using DR hostkey, in %INTERVAL% seconds...
timeout /t %INTERVAL%
SET HostKey=%DRHostKey%
goto Retry
) else (
echo Connection failed, aborting and sending an email notification.
echo.
echo From: %EmailFrom%
echo To: %EmailTo%
echo Subject: %EmailSubject%
echo Attachments: %EmailAttachment%
echo Message: %EmailBody%
powershell.exe -NoLogo -NoProfile -Command ^
"Send-MailMessage" ^
"-To %EmailTo%" ^
"-From '%EmailFrom%'" ^
"-Subject '%EmailSubject%'" ^
"-SmtpServer '%SMTPServer%'" ^
"-Body "%EmailBody%"" ^
"-Attachments %EmailAttachment%"
exit /b 1
)
)
exit /b %WINSCP_RESULT%

Comparing registry string value within a date range

I am writing a batch script which needs to compare registry data value string with ±3 days of todays date.
My REG QUERY returns a value:
HKEY_LOCAL_MACHINE\Software\Wow6432Node\KasperskyLab\Components\34\1103\1.0.0.0\Statistics\AVState
Protection_BasesDate REG_SZ 27-08-2018 08-53-00
I need to output to a file, depending if it is within the range or not.
Script:
REG QUERY "HKLM\Software\Wow6432Node\KasperskyLab\Components\34\1103\1.0.0.0\Statistics\AVState" /v "Protection_BasesDate" | Find "2018"
IF %ERRORLEVEL% == 1 goto end
If %ERRORLEVEL% == 0 goto makefile
:makefile
echo "{"product":"Override Antivirus","running":true,"upToDate":true}" > c:\ProgramData\CentraStage\AEMAgent\antivirus.json
:end
#exit
This solution takes this answer as base, so please review such an answer before post further questions here...
#echo off
setlocal EnableDelayedExpansion
rem Define the "Date to Julian Day Number" conversion function
set "DateToJDN(YMD)=( a=(YMD), y=a/10000, a%%=10000, m=a/100, d=a%%100, a=(m-14)/12, (1461*(y+4800+a))/4+(367*(m-2-12*a))/12-(3*((y+4900+a)/100))/4+d-32075 )"
rem Get the JDN of today's date minus/plus 3
for /F "tokens=2 delims==" %%t in ('wmic os get localdatetime /value') do set "dateTime=%%t"
set /A "todayMinus3=!DateToJDN(YMD):YMD=%dateTime:~0,8%!-3, todayPlus3=todayMinus3+6"
reg Get the date from REG QUERY command; the assumed output format is: Protection_BasesDate REG_SZ 27-08-2018 08-53-00
for /F "tokens=3-5 delims=- " %%a in (
'REG QUERY "HKLM\Software\Wow6432Node\KasperskyLab\Components\34\1103\1.0.0.0\Statistics\AVState" /v "Protection_BasesDate"'
) do set /A "BasesDate=!DateToJDN(YMD):YMD=%%c%%b%%a!"
if %BasesDate% geq %todayMinus3% if %basesDate% leq %todayPlus3% (
echo Date in range
)
There are many languages that can do much better than batch, but this might be a solution.
#echo off
set day=-3
for /f "delims=" %%i in ('reg query "HKLM\Software\Wow6432Node\KasperskyLab\Components\34\1103\1.0.0.0\Statistics\AVState" /v Protection_BasesDate" ^| findstr "2018"') do set "regdate=%%i"
for /f "tokens=1-3" %%a in ("%regdate%") do set "actual=%%c"
:check
echo >"%temp%\%~n0.vbs" s=DateAdd("d",%day%,now) : d=weekday(s)
echo>>"%temp%\%~n0.vbs" WScript.Echo year(s)^& right(100+month(s),2)^& right(100+day(s),2)
for /f %%a in ('cscript /nologo "%temp%\%~n0.vbs"') do set "result=%%a"
del "%temp%\%~n0.vbs"
set "yyyy=%result:~0,4%"
set "mm=%result:~4,2%"
set "dd=%result:~6,2%"
set "final=%dd%-%mm%-%yyyy%"
echo %final%
if %day% == 1 goto :EOF
if %actual% == %final% (echo Within 3 days!!) else (set /a day+=1 & goto :check)
We actually get the date of the system using cscript (yes I pipe to file, but you can run hybrid without the temp file) Then we take the past 3 days' dates and match them in the format of the registry key, if the key matches within 3 days, I just echo Within 3 days! There is also an if statement, if the day counter = 1, I exit the script, as we do not want to go into future and this loop forever if the counter if we do not stop it somewhere.
If it does work for you, you can simply remove the line print %final% and replace this line:
if %actual% == %final% (echo Within 3 days!!) else (set /a day+=1 & goto :check)
with this line:
if %actual% == %final% (echo "{"product":"Override Antivirus","running":true,"upToDate":true}" > "c:\ProgramData\CentraStage\AEMAgent\antivirus.json") else (set /a day+=1 & goto :check)

Find a number in text file and change signs for its row data using command line

I am learning batch scripting and the first task that came to me is a Text file that has more than 1000 rows and is something like this :
Organization, month,acct no.,data1,data2,data3,data4
orgA,Jan,1234,78900,78900,78900,78900
I need help in writing a batch file which should find a specific acct no. (for example: 3456) and put a '-' before data1, data2,data3,data4
I have tried :
1) using batch commands:
for /F "tokens=1 delims=," %%a in (%source%) do SET "org=%%a"
for /F "tokens=2 delims=," %%b in (%source%) do SET "month=%%b"
for /F "tokens=3 delims=," %%c in (%source%) do SET "acct=%%c"
for /F "tokens=4 delims=," %%d in (%source%) do SET "data1=%%d"
for /F "tokens=5 delims=," %%e in (%source%) do SET "data2=%%e"
for /F "tokens=6 delims=," %%f in (%source%) do SET "data3=%%f"
for /F "tokens=7 delims=," %%g in (%source%) do SET "data4=%%g"
set search=3456
set replace=-%data1%
FOR /F "tokens=* delims=," %%i in ("%source%") do
(set newline=%%i
IF /i %acct% EQU %search%
set newline=!newline:%org%,%month%,%acct%,%replace%!
echo !newline!>>%target%
)
2)VBS:
#echo objFile.WriteLine strNewText
#echo objFile.CloseConst ForReading =
#echo Const FileIn = "test.txt"
#echo Const FileOut = "test_adhoc.txt"
#echo Set objFSO = CreateObject("Scripting.FileSystemObject")
#echo Set objFile = objFSO.OpenTextFile(FileIn, ForReading)
#echo strText = objFile.ReadAll
#echo objFile.Close
#echo strNewText = Replace(strText, "*,*,3456,*,*,*,*", "*,*,3456,-*,-*,-*,- *")
#echo Set objFile = objFSO.OpenTextFile(FileOut, ForWriting)
#echo objFile.WriteLine strNewText
#echo objFile.Close
The problem with this type of management over large files is that Batch file processing is inherently slow, so any method that may speed up the process is good.
EDIT: Change the signs of the last four data.
2ND EDIT: ... when such a data may have decimal point
#echo off
setlocal EnableDelayedExpansion
set search=3456
rem Find the number of lines before the target one
for /F "delims=:" %%a in ('findstr /N "^.*,.*,%search%" source.txt') do set /A lines=%%a-1
rem Reading from the source file
< source.txt (
rem Copy the lines previous to target one
for /L %%i in (1,1,%lines%) do set /P "line=" & echo !line!
rem Read and process the target line
set /P "line="
for /F "tokens=1-7 delims=," %%a in ("!line!") do (
set "data1=-%%d" & set "data2=-%%e" & set "data3=-%%f" & set "data4=-%%g"
echo %%a,%%b,%%c,!data1:--=!,!data2:--=!,!data3:--=!,!data4:--=!
)
rem Copy the rest of lines
findstr "^"
) > output.txt
move /Y output.txt source.txt
In this code the target line is found in one operation via a findstr regex that search for the desired acct no. in the third comma-separated field of the line. The rest of the program is simple enough to be self-explanatory...
If you have any doubt of any command, you may review its help executing it with /? parameter; for example: findstr /?
Here is a possible way of doing what you want -- for integer values only (consult the explanatory remarks rem in the code):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=.\data.csv" & rem // (path to CSV file to modify)
set "_TMPF=%TEMP%\%_FILE%.tmp" & rem // (path to temporary file)
set "_ACCT=%~1" & rem // (account number to search, taken from first argument)
rem // Write modified CSV data to temporary file:
> "%_TMPF%" (
rem // Reset flag to indicate header (first row):
set "SKIP="
rem // Read CSV file line by line and extract seven tokens (columns):
for /F "tokens= 1-7 delims=, eol=," %%A in ('type "%_FILE%"') do (
rem // Check whether line is header, skip it from modification in case:
if defined SKIP (
rem // Check whether current account number matches:
if /I "%%C"=="%_ACCT%" (
rem // Assemble first three call values (do not modify):
set "PREF=%%A,%%B,%%C"
rem /* Invert sign of remaining four (numeric) cell values;
rem instead, you could also simply write this:
rem `echo(%%A,%%B,%%C,-%%D,-%%E,-%%F,-%%G`, but this
rem would lead to `--` if a number is already negative: */
set /A "VAL1=-%%D, VAL2=-%%E, VAL3=-%%F, VAL4=-%%G"
rem // Return modified line:
setlocal EnableDelayedExpansion
echo(!PREF!,!VAL1!,!VAL2!,!VAL3!,!VAL4!
endlocal
) else (
rem // Account number does not match, so return original line:
echo(%%A,%%B,%%C,%%D,%%E,%%F,%%G
)
) else (
rem // Line is the header, so return original line:
echo(%%A,%%B,%%C,%%D,%%E,%%F,%%G
rem // Next line is certainly not a header:
set "SKIP=#"
)
)
)
rem // Replace original CSV file with temporary file:
> nul move /Y "%_TMPF%" "%_FILE%"
endlocal
exit /B
Here is another way -- for decimal values, which are actually treated as strings (see remarks rem):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=.\data-dec.csv" & rem // (path to CSV file to modify)
set "_TMPF=%TEMP%\%_FILE%.tmp" & rem // (path to temporary file)
set "_ACCT=%~1" & rem // (account number to search, taken from first argument)
rem // Write modified CSV data to temporary file:
> "%_TMPF%" (
rem // Reset flag to indicate header (first row):
set "SKIP="
rem // Read CSV file line by line and extract seven tokens (columns):
for /F "tokens= 1-7 delims=, eol=," %%A in ('type "%_FILE%"') do (
rem // Check whether line is header, skip it from modification in case:
if defined SKIP (
rem // Check whether current account number matches:
if /I "%%C"=="%_ACCT%" (
rem // Assemble first three call values (do not modify):
set "PREF=%%A,%%B,%%C"
rem // Invert sign of remaining four (numeric) cell values:
set "VAL1=-%%D" & set "VAL2=-%%E" & set "VAL3=-%%F" & set "VAL4=-%%G"
rem // Return modified line, avoiding doubled minus-signs:
setlocal EnableDelayedExpansion
echo(!PREF!,!VAL1:--=!,!VAL2:--=!,!VAL3:--=!,!VAL4:--=!
endlocal
) else (
rem // Account number does not match, so return original line:
echo(%%A,%%B,%%C,%%D,%%E,%%F,%%G
)
) else (
rem // Line is the header, so return original line:
echo(%%A,%%B,%%C,%%D,%%E,%%F,%%G
rem // Next line is certainly not a header:
set "SKIP=#"
)
)
)
rem // Replace original CSV file with temporary file:
> nul move /Y "%_TMPF%" "%_FILE%"
endlocal
exit /B
Note: The powershell tag was only added to the question much later, so this answer should be considered out of competition.
PowerShell enables a concise and robust solution:
$acctNo = 3456
Import-Csv in.csv | ForEach-Object {
if ($_.'acct no.' -eq $acctNo) {
foreach($prop in (Get-Member -InputObject $_ data*)) {
$_.$($prop.name) = '-' + $_.$($prop.name)
}
}
$_
} # add, e.g., | Out-File -Encoding utf8 out.csv to save to a (different) file.
Import-Csv file reads the input CSV file and converts each row into a custom object whose properties correspond to the column values of each row.
The ForEach-Object cmdlet processes each such object:
Automatic variable $_ represents the input object at hand in each iteration.
if ($_.'acct no.' -eq $acctNo) checks for the account number of interest.
Get-Member -InputObject $_ data* uses reflection to return all properties on the input object whose name starts with data.
foreach(...) processes all matching properties in a loop.
$_.$($prop.name) = '-' + $_.$($prop.name) updates each matching property by prepending - to the existing value.
Note that you can't save the results directly back to the same file - unless you use (Import-Csv in.csv) instead of just Import-Csv in.csv, but that means that the entire input file will be read into memory as a whole.
(
for /f "tokens=1-7delims=," %%a in (yourfilename.txt) do (
if "%%c"=="3456" (echo %%a,%%b,%%c,-%%d,-%%e,-%%f,-%%g
) else (echo %%a,%%b,%%c,%%d,%%e,%%f,%%g)
)
)>processedfilename.txt
should work. Note that the entire for command is enclosed in parentheses to ensure that the output of the echoes is redirected to the processedfile name, which must not be the same as the source data filename.
Naturally, 3456 could be replaced by a variable if desired.
Here's the test batch I used - it is exactly the same as the code I posted, just with the filenames constructed to suit my test system.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q43354291.txt"
SET "outfile=%destdir%\outfile.txt"
(
for /f "tokens=1-7delims=," %%a in (%filename1%) do (
if "%%c"=="3456" (echo %%a,%%b,%%c,-%%d,-%%e,-%%f,-%%g
) else (echo %%a,%%b,%%c,%%d,%%e,%%f,%%g)
)
)>"%outfile%"
GOTO :EOF
Here's the input file I used - it's simply your data with a couple of lines duplicated and fixed to suit account=3456
Organization, month,acct no.,data1,data2,data3,data4
orgA,Jan,1234,78900,78900,78900,78900
orgA,Jan,3456,78900,78900,78900,78900
orgA,Jan,6789,78900,78900,78900,78900
and here's the output file
Organization, month,acct no.,data1,data2,data3,data4
orgA,Jan,1234,78900,78900,78900,78900
orgA,Jan,3456,-78900,-78900,-78900,-78900
orgA,Jan,6789,78900,78900,78900,78900
which appears to be what you require.

Select Random Files From Txt File and Save to Another Txt - VBScript

I have a text file with 350.000+ lines. I need to select 100 random lines from that file and save them to a separate text file.
Is this possible with vbscript?
The file is UTF-8 will this be an issue?
I may need to do something more complex after this like: Select 100 random lines and save them to a text file from multiple text files (each containing 350k+ lines). Will this be achievable as well?
Sub Randomise
Randomize
Set rs = CreateObject("ADODB.Recordset")
With rs
.Fields.Append "RandomNumber", 4
.Fields.Append "Txt", 201, 5000
.Open
Do Until Inp.AtEndOfStream
.AddNew
.Fields("RandomNumber").value = Rnd() * 10000
.Fields("Txt").value = Inp.readline
.UpDate
Loop
.Sort = "RandomNumber"
Do While not .EOF
Outp.writeline .Fields("Txt").Value
.MoveNext
Loop
End With
End Sub
Randomises lines in a file.
Sub Cut
Set rs = CreateObject("ADODB.Recordset")
With rs
.Fields.Append "LineNumber", 4
.Fields.Append "Txt", 201, 5000
.Open
LineCount = 0
Do Until Inp.AtEndOfStream
LineCount = LineCount + 1
.AddNew
.Fields("LineNumber").value = LineCount
.Fields("Txt").value = Inp.readline
.UpDate
Loop
.Sort = "LineNumber ASC"
If LCase(Arg(1)) = "t" then
If LCase(Arg(2)) = "i" then
.filter = "LineNumber < " & LCase(Arg(3)) + 1
ElseIf LCase(Arg(2)) = "x" then
.filter = "LineNumber > " & LCase(Arg(3))
End If
ElseIf LCase(Arg(1)) = "b" then
If LCase(Arg(2)) = "i" then
.filter = "LineNumber > " & LineCount - LCase(Arg(3))
ElseIf LCase(Arg(2)) = "x" then
.filter = "LineNumber < " & LineCount - LCase(Arg(3)) + 1
End If
End If
Do While not .EOF
Outp.writeline .Fields("Txt").Value
.MoveNext
Loop
End With
End Sub
Can chop top 100 lines from a file.
Cut
filter cut {t|b} {i|x} NumOfLines
Cuts the number of lines from the top or bottom of file.
t - top of the file
b - bottom of the file
i - include n lines
x - exclude n lines
Example
filter cut t i 5 <"%systemroot%\win.ini"
---
Random
filter random
filter rand
Randomises lines of text in a file. Used to unsort a list.
Example
filter random < "%windir%\win.ini"
These are samples from another program. Common declarations are
Set Arg = WScript.Arguments
set WshShell = createObject("Wscript.Shell")
Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
General use is
Filter reads and writes standard in and standard out only. These are only available in a command prompt.
cscript filter <inputfile >outputfile
cscript filter <inputfile | other_command
other_command | cscript filter >outputfile
other_command | cscript filter | other_command
t
This is the batch file I use to call the above functions. The batchfile installs itself into the path if needed. This allows the vbs script (filter.vbs) to be used in a command prompt as if it's an exe file.
#echo off
Rem Make sure filter.vbs exists
set filter=
set filterpath=
Call :FindFilter filter.vbs
Rem Add filter.bat to the path if not in there, setx fails if it's already there
setx path %~dp0;%path% 1>nul 2>nul
Rem Test for some command line parameters
If not "%1"=="" goto main
echo.
echo -------------------------------------------------------------------------------
echo.
echo Filter.bat
echo ==========
echo.
echo The Filter program is a vbs file for searching, replacing, extracting, and
echo trimming console output and text files.
echo.
echo Filter.bat makes Filter.vbs easily usable from the command line. It
echo controls unicode/ansi support and debugging.
echo.
echo Type Filter Help or Filter HTMLHelp for more information.
echo.
cscript //nologo "%filter%" menu
Goto :EOF
:Main
echo %date% %time% %~n0 %* >>"%~dp0\FilterHistory.txt"
rem echo Batch file ran
rem echo %*
Rem /ud Unicode and Debug
If %1==/ud FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u //x %%j&Goto :EOF
Rem /u Unicode
If %1==/u FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u %%j&Goto :EOF
Rem /d Ansi Debug
If %1==/d FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //x %%j&Goto :EOF
Rem -ud Unicode and Debug
If %1==-ud FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u //x %%j&Goto :EOF
Rem /u Unicode
If %1==-u FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u %%j&Goto :EOF
Rem -d Ansi Debug
If %1==-d FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //x %%j&Goto :EOF
Rem ANSI
cscript "%filter%
" //nologo %*&Goto :EOF
Goto :EOF
:FindFilter
If Exist "%~dpn0.vbs" set filter=%~dpn0.vbs&set filterpath=%~dp0&goto :EOF
echo find filter 1
If Not "%~dpnx$PATH:1" == "" set filter=%~dpnx1&set filterpath=%~dp1&goto :EOF
echo find filter 2
If Exist "%temp%\filter.vbs" set filter=%temp%\filter.vbs&set filterpath=%temp%&goto :EOF
copy "%~dpnx0" "%~dpn0.bak"
if not errorlevel 1 (
echo creating "%~dpn0.vbs"
goto :EOF
)
copy "%~dpnx0" "%temp%\filter.bak"
echo Error %errorlevel%
if not errorlevel 1 (
echo creating "%temp%\filter.bak"
Goto :EOF
)
Goto :EOF
I solved this like this:
randomize
set objFSO = CreateObject("Scripting.FileSystemObject")
Set numberDic = CreateObject("Scripting.Dictionary")
set objInFile = objFSO.OpenTextFile("C:\Users\Mega\Desktop\250kWords.txt", 1, true, 0)
set objOutFile = objFSO.OpenTextFile("C:\Users\Mega\Desktop\100WordsSelected.txt", 2, true, 0)
strLines = objInFile.ReadAll
arrLines = split(strLines, vbNewLine)
intUpperLimit = ubound(arrLines)
numPicks = 100
'number of random picks must be less than or
'equal to the number of lines in the input file
if intUpperLimit < numPicks then
numPicks = intUpperLimit
end if
Do Until numberDic.Count = numPicks
index = int(rnd() * intUpperLimit) + 1
intRandom = arrLines(index)
intRandom = Trim(intRandom)
'if blank lines exist in text file, don't add them
if intRandom <> "" then
'if the line chosen is not in the dictionary object, add it
if not numberDic.exists(intRandom) then
numberDic.Add intRandom, intRandom
end if
end if
Loop
for each item in numberDic
objOutFile.WriteLine item
next
objInFile.close
objOutFile.close