Extract list of path in a file using batch script - windows

Here is my text file:
==================================================
Folder : D:\T\New folder
==================================================
==================================================
Folder : D:\T\Z-Ai
==================================================
==================================================
Folder : D:\T\Z-BiN
==================================================
I need to extract the paths from this file, so I have something like this:
D:\T\New folder
D:\T\Z-Ai
D:\T\Z-BiN
It seems I should use findstr TargetWord TargetFile.txt command. and Also it seems I can use regex like this: findstr /r "^[a-z][a-z]$ ^[a-z][a-z][a-z]$"
But I do not know how to loop through found targets or get the list of output. any help is really appreciated.

Based on your comment, you want to use the result to perform an xcopy task, it seems you really want something like this. Note I used example.txt as input file, and DESTINATION where you should add your destination, including the relevant xcopy switches you require:
#echo off
for /f "tokens=2*" %%i in ('type example.txt ^| findstr /i ":\\"') do xcopy "%%~j\*" DESTINATION
Alternatively we can use the findstr directly on Folder
#echo off
for /f "tokens=2*" %%i in ('type example.txt ^| findstr /i "Folder"') do xcopy "%%~j\*" DESTINATION

You can do like this :
#echo off
Title Extract list of path in a file using batch script
set "TxtList=MyList.txt"
Set "OutPutData=Output.txt"
Call :Extract "%TxtList%" "%OutPutData%"
Start "" "%OutPutData%"
Exit
::*****************************************************
:Extract <InputData> <OutPutData>
(
echo Data = WScript.StdIn.ReadAll
echo Data = Extract(Data,"[\w]:(\\[0-9\sA-Za-z\-]*)+"^)
echo WScript.StdOut.WriteLine Data
echo '************************************************
echo Function Extract(Data,Pattern^)
echo Dim oRE,oMatches,Match,Line
echo set oRE = New RegExp
echo oRE.IgnoreCase = True
echo oRE.Global = True
echo oRE.Pattern = Pattern
echo set oMatches = oRE.Execute(Data^)
echo If not isEmpty(oMatches^) then
echo For Each Match in oMatches
echo Line = Line ^& Trim(Match.Value^) ^& vbcrlf
echo Next
echo Extract = Line
echo End if
echo End Function
echo '************************************************
)>"%tmp%\%~n0.vbs"
cscript /nologo "%tmp%\%~n0.vbs" < "%~1" > "%~2"
If Exist "%tmp%\%~n0.vbs" Del "%tmp%\%~n0.vbs"
exit /b
::****************************************************

For Windows. you can use powershell.
select-string -Path c:\tmp\file.txt -Pattern '[A-Z]:(\\[0-9\ A-Za-z\-]*)+' -AllMatches | % { $_.Matches } | % { $_.Value }

In my opinion, For /F is all you need for the task. Although using Type may be useful in some situations, there's no need to use find.exe or findstr.exe for this task as you don't need to match a particular glob/pattern:
#For /F "EOL==Tokens=2*UseBackQ" %%A In ("TargetFile.txt")Do #"%__AppDir__%xcopy.exe" "%%B" "Destination\" /Options
Please note that it may be wise, if there's a chance that one or more of theses Folders do not exist, that you prepend using If Exist "%%B\". Importantly, if each of the lines containing the Folder paths, is space padded up to the end of its line, this solution will not work for you.

Related

Is there a command that can be moved to a folder by file name in Windows?

I want to read the file name with the command and automatically move it to the folder with the same name. What should I do?
example:
before processing
after processing
If I have files and folders with the same name, I want to move them to a folder with the same name.
What should I do? Do I have a cmd command?
I will provide both a solution to this exact question, and an alternative that I would suggest to handle this situation.
==========
~ Solution ~
==========
Copy/Paste the code below into an empty file, save, and execute.
#echo off
for /f "tokens=1,* delims=_" %%a in ('dir /b *.xlsx') do (
if not "%%a_%%b"=="%~nx0" (
if not exist %%a mkdir %%a
move "%%a_%%b" "%%a\"
)
)
You can change the "*.xlsx" to any other file extension, or change to "*.*" to work with ANY file extension.
Keep in mind though, this ONLY works with filenames that are formatted like the way you mentioned in your question.
===================
~ Alternative Solution~
===================
I would suggest the Shell Extension "Files 2 Folder" as an alternative. I came across a situation where I needed something similar to what you're asking a couple years ago, and this ended up working out great.
https://www.dcmembers.com/skwire/download/files-2-folder/
Here is another approach using regex in vbscript with a batch file :
#echo off & color 0A
Title Extract Title using Regex in vbscript
SetLocal EnableDelayedExpansion
#for /f "delims=" %%a in ('dir /b *.xlsx') do (
Call :Extract_Title "%%a" Title
If Defined Title (
If Not Exist "!Title!\" MkDir "!Title!\"
Move /-Y "%%a" "!Title!\"
)
)
Pause & Exit
::----------------------------------------------------------------------------------------
:Extract_Title <InputFile> <Title to be Set>
>"%tmp%\%~n0.vbs" (
echo WScript.StdOut.WriteLine Extract_Title(Data^)
echo Function Extract_Title(Data^)
echo Data = Wscript.Arguments(0^)
echo Set re = New RegExp
echo re.Global = True
echo re.IgnoreCase = True
echo re.Pattern = "(\S+|\S.+)_"
echo For Each Match in re.Execute(Data^)
echo Title = Match.SubMatches(0^)
echo Next
echo Extract_Title = Title
echo End Function
)
#for /f "delims=" %%A in ('cscript /nologo "%tmp%\%~n0.vbs" "%~1"') do set "%2=%%A"
If Exist "%tmp%\%~n0.vbs" Del "%tmp%\%~n0.vbs"
Exit /B
::----------------------------------------------------------------------------------------

How to get only the first sequence of numbers in a listing using batch or powershell

What I need is the first sequence of a number in a listing:
The command:
for /f "delims=" %%a in (notas.txt) do #echo %%a
Returns:
Compra cfme NF 12345 de 123 CIA ABC
Pgto dupl. 12345 - 123 CIA ABC
Compra cfme NFS 654321-CIA CBC
Pgto NF 654321 de CIA CBC
But what I need is:
12345
12345
654321
654321
Thanks in advance
There are numerous PowerShell solution/techniques that can perform what is required.
The switch statement can be used with the -File and -Regex parameters.
switch -Regex -File notas.txt {
'\d+' { $Matches[0] }
}
You can also use the Match method from the regex class:
Get-Content notas.txt | Foreach-Object {
[regex]::Match($_,'\d+').Value
}
Both solutions rely on regex matching with \d+ matching one or more consecutive digits. Since we are doing a single match per line, the first match is the only match returned. The regex class method Matches returns multiple matches per string input.
With a Batch file using regex in vbscript you can do something like this :
Demo Here
#echo off & color 0A
Title Extract Numbers from String using Regex with vbscript
Set "InputFile=%~dp0notas.txt"
Set "OutPutFile=%~n0_OutPutFile.txt"
Call :Extract_Number "%InputFile%" CON
Call :Extract_Number "%InputFile%" "%OutPutFile%"
TimeOut /T 3 /NoBreak>nul
If Exist "%OutPutFile%" Start "" "%OutPutFile%" & Exit
::-----------------------------------------------------------------------------------
:Extract_Number <Input> <OutPut>
(
echo WScript.StdOut.WriteLine Extract_Number(Data^)
echo Function Extract_Number(Data^)
echo Data = "%~1"
echo Data = WScript.StdIn.ReadAll
echo Set re = New RegExp
echo re.Global = True
echo re.IgnoreCase = True
echo re.Pattern = "\d{5,}"
echo For Each Match in re.Execute(Data^)
echo Number = Number ^& Match.Value ^& vbCrLF
echo Next
echo Extract_Number = Number
echo End Function
)>"%tmp%\%~n0.vbs"
cscript //nologo "%tmp%\%~n0.vbs" < "%~1" > "%~2"
If Exist "%tmp%\%~n0.vbs" Del "%tmp%\%~n0.vbs"
Exit /B
::----------------------------------------------------------------------------------
This first code does what your question asks, but not what your expected results show:
#echo off
:: Pass the entire line to a subroutine
for /f "delims=" %%a in (notas.txt) do call :process %%a
goto :eof
:process
:: Check if we've evaluated the entire line
if "%1"=="" (
echo No number was found in this line
goto :eof
)
:: Check if the current parameter is only numbers
:: If it is, then echo and move on to the next line
:: If not, use shift to evaluate the next parameter
echo %1|findstr /i /r "[^0-9]" >nul && shift && goto :process
echo %1
goto :eof
2 things. First, I don't know what you want to do if a number isn't found in the line. In the code above I just echo "No number was found in this line".
Second, I presumed "number" to be fully delimited with standard spaces as delimiters. Thus, the code above does NOT return 654321 from the line Compra cfme NFS 654321-CIA CBC because 654321-CIA is not a number delimited by spaces. If you want additional delimiters, then change this line above:
for /f "delims=" %%a in (notas.txt) do call :process %%a
to:
for /f "tokens=1-10 delims=-., " %%a in (notas.txt) do call :process %%a %%b %%c %%d %%e %%f %%g %%h %%i %%j
adding whatever delimiters you want (don't forget a space before the double quote). This line is good for up to 10 entries on a given line. Going up to 26 using tokens=1-26 and %%a through %%z is pretty easy.
Finally -- if you want to pull a non-delimited number -- then that would be a completely different approach. An example would be getting 1356 from PC1356 NLA LOA; or getting 35232 from PC LI-D 35232NDA TTH.

Extraction of string from a line using batch

I have data in the below manner:
adb.hghgjjk.hkdhdl.Connhhhjj=hjkld\:hjkld\:thin\:hjdkdl\:3000\:abcdefg
I want to extract "abcdefg" from the above line using batch.
Above data can be changing so we need to read from the end of the line to backside and stop near : (colon) delimiter and extract it.
Any sugeestions?
Normally we do not give out code without the user at least making an attempt at trying to write some code and put some effort into researching the problem. Simple philosophy behind that is teaching a man to fish versus giving them the fish.
Give this a try.
#echo off
set "string=adb.hghgjjk.hkdhdl.Connhhhjj=hjkld:hjkld:thin:hjdkdl:3000:abcdefg"
set "first=%string::=" & set "last=%"
echo %last%
pause
If your data will never have a semicolon that you need to keep you could do this as well.
#echo off
set "string=adb.hghgjjk.hkdhdl.Connhhhjj=hjkld:hjkld:thin:hjdkdl:3000:abcdefg"
set "string=%string::=;%"
FOR %%G IN (%string%) do set "last=%%G"
echo %last%
pause
And one more example for good measure. The nice thing about batch files is alot of times there is more than one way to skin a cat.
#echo off
set "string=adb.hghgjjk.hkdhdl.Connhhhjj=hjkld:hjkld:thin:hjdkdl:3000:abcdefg"
:loop
FOR /F "tokens=1* delims=:" %%G IN ("%string%") do (
set "last=%%G"
IF NOT "%%~H"=="" (
SET "string=%%~H"
GOTO loop
)
)
echo %last%
pause
PowerShell can use regex expressions. The result is put into the R variable. If there is no match, R will be nothing.
#ECHO OFF
SET "S=adb.hghgjjk.hkdhdl.Connhhhjj=hjkld\:hjkld\:thin\:hjdkdl\:3000\:abcdefg"
SET "R="
FOR /F %%a IN ('powershell -NoLogo -NoProfile -Command ^
" '%S%' | Where-Object { $_ -match '.*:(.*$)' } | ForEach-Object { $Matches[1] } "') DO (SET "R=%%a")
ECHO R is %R%

Get a MD5 value from a file using findstr in CMD

I have the following file contents from which I want to extract the MD5 hash value thats on line 2.
How can I do this in a Windows batch file? Unfortunately using powerscript is not an option.
Herewith the input file ( file.txt )
MD5hashoffile20160613190010_Address
f4f855c5cb40767a7227b506f641ceef
CertUtil:-hashfilecommandcompletedsuccessfully.
I wanted to use the findstr utility but the regex I use must be wrong since it's not returning anything.
findstr /R "[a-fA-F0-9]{32}" file.txt
I appreciate any advice.
Thanks
UPDATE :
I have added the full solution in the answer section.
After some trial and error I found a solution that works :
findstr /R "^[a-fA-F0-9]*$" file.txt
Updated Answer with full solution :
SETLOCAL ENABLEDELAYEDEXPANSION
SET "FILESIZE=0"
SET "RECORDCOUNT=0"
SET "MD5HASH="
SET "TEMPHASH="
SET "FILESETREPORT=_UNSET"
SET "LINE=0"
SET "COLUMNS=TableName|RecordCount|FileSize|FileHash"
echo "============================="
echo "= Starting FileSize process ="
echo "============================="
for %%F in (*.csv) do (
echo "Process A CSV File"
for /f "tokens=1,2,3,4 delims=^_" %%A IN ("%%~nF") do (
SET "TABLENAME=%%D"
SET "FILESIZE=%%~zF"
if "!FILESETREPORT!" == "_UNSET" (
SET "FILESETREPORT=%%A_%%B_%%C_FilesetReport.csv"
:: Initialize the headers
echo !COLUMNS! > !FILESETREPORT!
)
)
echo "Get RecordCount in CSV"
if "!TABLENAME!" NEQ "FilesetReport" (
for /f "tokens=*" %%I in ('more +1 %%F ^| find /v /c ""') do SET "RECORDCOUNT=%%I"
echo "Generate File MD5 Hash"
certUtil -hashfile %%~nxF MD5 > hashfile
echo "Get the hash from the file"
for /f "skip=1 tokens=*" %%A in (hashfile) do (
SET "TEMPHASH=%%A"
:: call :cleanHash
if !LINE! == 0 SET "LINE=1" && call :cleanHash
)
:: Reset the Line Number
SET "LINE=0"
echo "Save File Details to FieldsetReport"
echo "RecordCount : !RECORDCOUNT!"
echo "FileSize : !FILESIZE!"
echo "MD5Hash : !MD5HASH!"
echo "TableName : !TABLENAME!"
SET "OUTPUTLINE=!TABLENAME!|!RECORDCOUNT!|!FILESIZE!|!MD5HASH!"
echo !OUTPUTLINE! >> !FILESETREPORT!
:: Cleanup
del hashfile
)
)
echo "File Processing Completed"
exit /b 0
:cleanHash
echo "Remove all spaces from the MD5 hash"
:: for /f "delims=" %%a in ('findstr /R "^[a-fA-F0-9]*$" !TEMPHASH!') do SET TEMPHASH=%%a
SET "MD5HASH=!TEMPHASH: =!"
echo "********************************************************************"
echo !MD5HASH!
ENDLOCAL
You're better off using this:
#echo off
for /f "skip=1" %%a in (file.txt) do set "hash=%%a" &goto breakLoop
:breakLoop
echo %hash%
pause
This should work even if another line also contains only hexadecimal characters, and has the added benefit of putting the md5 hash in a variable, ready to be used.

Windows Batch Script: list all files with name, path, size and owner into a csv file

I have a script which can list all files under a folder and its subforlders, with some properties such as path, file name, modified date and size. But, I can't add one extra property, file owner.
#ECHO off
SET v1=%%~dpF
SET v2=%%~nxF
SET v3=%%~zF
(for /r %%F in (*) do #echo "%v1%","%v2%",%v3%) > test.csv
PAUSE
Basically I want to add a 4th parameter, which should show file owner. It is in Windows 7 environment.
You can use the dir command with the /q switch to include the owner of each file.
#ECHO OFF
SetLocal EnableDelayedExpansion
for /r %%a in (*) do for /f "tokens=5" %%b in ('dir /q "%%~fxa" ^| findstr "%%~nxa"') do (
echo "%%~dpa","%%~nxa","%%~za","%%b"
) >> test.csv
This will always append to test.csv, if you want to always recreate test.csv you can encase your entire for loop in parenthesis (as you had);
#ECHO OFF
SetLocal EnableDelayedExpansion
(for /r %%a in (*) do for /f "tokens=5" %%b in ('dir /q "%%~fxa" ^| findstr "%%~nxa"') do (
echo "%%~dpa","%%~nxa","%%~za","%%b"
)) > test.csv
Not exactly what you asked for, but I adapted a PowerScript to show what you ask for. Just update the PARAM section with your file and folder names, copy and paste into PowerShell and hit enter twice:
PARAM (
$Path = 'C:\Users\PATHHERE\',
$report = 'C:\Users\USERNAME\Desktop\OUTPUTFILENAMEHERE.csv'
)
$LastWrite = #{
Name = 'Last Write Time'
Expression = { $_.LastWriteTime.ToString('u') }
}
$Owner = #{
Name = 'File Owner'
Expression = { (Get-Acl $_.FullName).Owner }
}
$HostName = #{
Name = 'Host Name'
Expression = { $env:COMPUTERNAME }
}
Get-ChildItem -Recurse -Path $Path |
select $HostName, $Owner, Name, Directory, $LastWrite, Length |
Export-Csv -NoTypeInformation $Report
This script adapted from info found here. I find batch files to be more and more trouble to deal with these days, and PowerShell is very flexible. The guys over at serverfault.com will no doubt be able to help you better with these kinds of questions.

Resources