I have a template document that I want to convert to another file with a user defined name. The following is the code I have pieced together.
rem #echo off
setlocal enableDelayedExpansion
cls
:Check_Filename
set "_Filename="
set /p _Filename=Enter filename to be created:
if not defined _Filename echo You must enter a value. Try again.&goto Check_Filename
set "test=%_Filename:~0,1%"
for %%C in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if defined test set "test=!test:%%C=!"
if defined test echo Invalid input. Try again.&goto Check_Filename
if not defined test echo %_Filename%
Set "errorlevel="
echo %_Filename% | findstr /i /R ".java" > nul
if %errorlevel% == 0 (
echo Java extention located
type f:\java\Template.txt > f:\java\%_Filename%
echo %errorlevel%
) else (
echo Java extention not located
echo %errorlevel%
type f:\java\Template.txt > f:\java\%_Filename%.java
)
)
It works but because the file is being used to create the backbone of Java script I want the FOR statement to evaluate the case of the first character which it does not presently do. I tried using HEX representation of these characters in the FOR statement as well, but without success.
Could someone please help me?
Thank you.
Try this:
#echo off & setlocal
:Check_Filename
set "_Filename="
set /p "_Filename=Enter filename to be created: "
if not defined _Filename echo You must enter a value. Try again.&goto:Check_Filename
echo(%_Filename:~0,1% | findstr /r "[ABCDEFGHIJKLMNOPQRSTUVWXYZ]" || (echo Invalid input. Try again.&goto:Check_Filename)
Related
I need to initialize multiple env vars only on certain conditions, I cannot use anything but command line.
For the example of my problem I am going to take a symple case of initializing an alphabet.
First cmd script is :
#echo OFF
set PATH=%PATH%;"%~dp0"
IF "%_ALPHABET%"=="" (
echo "DEFINE"
call setEnvA
call set "_ALPHABET=%_ALPHABET%;b"
) ELSE (
echo "ALREADY DEFINE"
set _ALPHABET=
set A_ADDED=
)
setEnvA cmd is :
IF "%A_ADDED%"=="" (
set A_ADDED=OK
set _ALPHABET=%_ALPHABET%;a
)
I was expecing
;a;b
as a result, but I get only
;b
I tried to throw random delayedexpansion but without any result. I am starting to think that this is not possible and I should do some dirty goto.
The contents of environment variable _ALPHABET is being substituted within the parenthesis before the call to setEnvA is performed. You need to do something like:
#echo OFF
set PATH=%PATH%;"%~dp0"
IF "%_ALPHABET%"=="" (
echo "DEFINE"
call setEnvA
call :set_ALPHABET
) ELSE (
echo "ALREADY DEFINE"
set _ALPHABET=
set A_ADDED=
)
exit /b
:set_ALPHABET
set "_ALPHABET=%_ALPHABET%;b"
I want to integrate a vbscript that use a function with a symmetric encryption function into a batch file that ask user to enter its password using powershell to mask the input text :
#echo off
set "psCommand=powershell -Command "$pword = read-host 'Enter Password' -AsSecureString ; ^
$BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); ^
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)""
for /f "usebackq delims=" %%p in (`%psCommand%`) do set password=%%p
echo %password%
pause
Vbscript code :
Encrypted_String = Crypt("123456789")
wscript.echo Encrypted_String
Decrypted_String = Crypt(Encrypted_String)
wscript.echo Decrypted_String
'***************************************************************************
Function Crypt(text)
Dim i,a
For i = 1 to len(text)
a = i mod len(255)
if a = 0 then a = len(255)
Crypt = Crypt & chr(asc(mid(255,a,1)) XOR asc(mid(text,i,1)))
Next
End Function
'***************************************************************************
So, i'm trying to combine those codes into a batch file like that :
The combined Batch-File :
#echo off & Setlocal EnableDelayedExpansion
Title %~n0 - Encrypt_Decrypt passwords by Hackoo 2016
Mode 60,5 & Color 0E
:Main
Call :Clean
Call :InputPassword "Please choose your password" MyPass
Call :Crypt_Decrypt !MyPass! >%tmp%\MyCryptedPass.txt
(set /p CryptPass=)<%tmp%\MyCryptedPass.txt
echo The encrypted password is :!CryptPass!
pause
cls
Call :Crypt_Decrypt !CryptPass!>%tmp%\MyPlaintextPass.txt
(set /P MyPlaintextPass=)<%tmp%\MyPlaintextPass.txt
echo The password in plain text is : !MyPlaintextPass!
pause
Goto :Main
::********************************************************************************
:InputPassword
Cls
echo.
set "psCommand=powershell -Command "$pword = read-host '%1' -AsSecureString ; ^
$BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); ^
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)""
for /f "usebackq delims=" %%p in (`%psCommand%`) do set %2=%%p
Goto :eof
::********************************************************************************
:Crypt_Decrypt
Call :Clean
(
echo StringEnCrypted = Crypt("%~1"^)
echo wscript.echo StringEnCrypted
echo '****************************************************************************
echo Function Crypt(text^)
echo Dim i,a
echo For i = 1 to len(text^)
echo a = i mod len(255^)
echo if a = 0 then a = len(255^)
echo Crypt = Crypt ^& chr(asc(mid(255,a,1^)^) XOR asc(mid(text,i,1^)^)^)
echo Next
echo End Function
echo '****************************************************************************
)>%tmp%\Crypt_Decrypt.vbs
cscript /nologo %tmp%\Crypt_Decrypt.vbs
goto :eof
::********************************************************************************
:Clean
If Exist %tmp%\Crypt_Decrypt.vbs Del %tmp%\Crypt_Decrypt.vbs
goto :eof
::********************************************************************************
So, this last Batch script can encrypt and dercypt strings; but when i enter only numbers or something like this it didn't work ???
For example if enter :
123456789 as password ==> Not Ok
hackoo123 as password ==> Not Ok
Thank you for your help !
Your encryption can produce null (ascii decimal 0), carriage return (ascii decimal 13), and newline (ascii decimal 10) bytes, all of which will wreak havoc when you write the value to a file and then try to read it back in again. It is possible to work with carriage return and newline within environment variables, but null is an absolute no go.
Well, almost end of story. Batch can use FC in binary mode to read a binary file, byte by byte, outputting each byte in hex notation. (see HEXDUMP.BAT) But I don't think you want to go there.
If you want to deal with encrypted values within batch environment variables, then I suggest you come up with a new encryption scheme that avoids the troublesome bytes. At a minimum you must avoid null bytes.
Another option would be to abandon symmetric encryption, and let VBS convert the encrypted form into hex notation before you write it to disk.
Which leads me to another concern - Why are you writing a password to disk? That does not sound like a good idea.
Final note - Passing arbitrary strings on the command line is fraught with peril. You are better off passing the name of an environment variable that contains the value, and then let the called routine get the value from the variable. Certainly VBS can read an environment variable given the variable name.
Just got a new phone and have temporarily copied the old ones files onto my PC C:\OldPhone\
On my PC are all my photos, in various folders below D:\Photos.
I want some code to list all the .jpg files below C:\OldPhone\ which are not anywhere below D:\Photos\
Does that make sense? Just to stress, the folder structures are not identical and I don't mind where the file is, just as long as it's there. Filename comparison would do for starters, option to add size would be a bonus!
CMD, VBS or powershell would be good, but anything visual studio can cope with would be ok too.
try this:
for /r "D:\Photos" %%a in (*.jpg) do set "$%%~na=1"
for %%a in (C:\OldPhone\*.jpg) do if not defined $%%~na echo %%~a not in d:\photos
cmd has associative arrays, like awk. This doesn't work with file names containing =.
This should do the trick in PowerShell"
$ht=#{} # initialize empty hashtable
dir C:\OldPhone\*.jpg -r -file | Foreach {$ht["$($_.Name):$($_.Length)"] = $_.FullName}
dir D:\Photos\*.jpg -r file | Foreach {$ht.Remove("$($_.Name):$($_.Length)")}
$ht # dump remaining hashtable contents
This also takes into account the size of the file in case you have multiple files with the same name. Ideally, to really ensure their are the same, you would include the MD5 file hash instead of the file length as part of the hashtable $ht key for each file. Note that the -file parameter is new in PowerShell V3. You probably don't need it unless you have some folders with .jpg as part of their name.
For /R %%i In (newfiles\*.jpg) Do Call :Check "%%~fi"
GoTo :EOF
:Check
For /R %%i In (existingfiles\*.jpg) Do If /I "%%~nxi"=="%~nx1" GoTo :Found
Echo File %1 doesn't already exist!
GoTo :EOF
:Found
Echo File %1 already exists!
GoTo :EOF
Here's what I ended up with, based on Endoro's answer. I really should put the folder locations into variables, but it works now, so that's all I need! I should also put the setlocal ... endlocal lines into a subroutine too.
Now I look at it, OLDFOLDER is a daft name too. This is poor coding!
It copies any missing .jpg or .mp4 files into a folder for ease of copying.
echo off
set OLDFOLDER=C:\OldPhone
cls
echo Checking for files in %OLDFOLDER% which aren't in D:\Pictures
del /f /q "D:\Documents\MissingFiles\*"
setlocal
for /r "D:\Photos" %%a in (*.jpg) do set "$%%~nxa=1"
for /r "%OLDFOLDER%" %%a in (*.jpg) do if not defined $%%~nxa copy "%%~a" "D:\Documents\MissingFiles\"
endlocal
setlocal
for /r "D:\Photos" %%a in (*.mp4) do set "$%%~nxa=1"
for /r "%OLDFOLDER%" %%a in (*.mp4) do if not defined $%%~nxa copy "%%~a" "D:\Documents\MissingFiles\"
endlocal
if exist "D:\Documents\MissingFiles\*.*p*" (
echo Files missing from D:\Photos copied to D:\Documents\MissingFiles\
) else (
echo There are no files in %OLDFOLDER% which aren't in D:\Photos
)
pause
Use fciv (and grep):
fciv .\old -r | grep jpg > old.txt
fciv .\new -r | grep jpg > new.txt
To get
old.txt
6d5f1279d4deccbaeef5d074b13ed2f4 .\old\b\100_1608.jpg
d95e29e2c0172dea438b12c418b09fd3 .\old\b\100_1610.jpg
19f9cda002c951f7a9f870ce74fb1224 .\old\b\100_1601.jpg
32b154f796303a8e9caff0c9d55ba713 .\old\b\100_1600.jpg
26ff43419c4f30764fb015f6d7c869c1 .\old\b\100_1609.jpg
d95e29e2c0172dea438b12c418b09fd3 .\old\a\100_1610.jpg
19f9cda002c951f7a9f870ce74fb1224 .\old\a\100_1601.jpg
32b154f796303a8e9caff0c9d55ba713 .\old\a\100_1600.jpg
new.txt
545b2121a3af2a8e5aa3c5946b450e87 .\new\c\100_1605.jpg
02a1638739302f3c17253beaa3fe9c1b .\new\c\100_1603.jpg
d95e29e2c0172dea438b12c418b09fd3 .\new\c\100_1610.jpg
19f9cda002c951f7a9f870ce74fb1224 .\new\c\100_1601.jpg
32b154f796303a8e9caff0c9d55ba713 .\new\a\100_1600.jpg
use a schema.ini file:
[old.txt]
Format=Delimited( )
ColNameHeader=False
Col1=MD5 CHAR
Col2=PATH CHAR
[new.txt]
Format=Delimited( )
ColNameHeader=False
Col1=MD5 CHAR
Col2=PATH CHAR
and VBScript:
Option Explicit
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
Dim oDb : Set oDb = CreateObject("ADODB.Connection")
Dim sCS : sCS = Join(Array(_
"Provider=MSDASQL" _
, "Driver={Microsoft Text Driver (*.txt; *.csv)}" _
, "DBQ=" & goFS.GetAbsolutePathName("..\data") _
), ";")
Dim sSQL : sSQL = "SELECT O.* FROM [old.txt] O LEFT JOIN [new.txt] N ON O.MD5 = N.MD5 WHERE N.MD5 IS NULL"
oDb.Open sCS
Dim oRS : Set oRS = oDb.Execute(sSQL)
If Not oRS.EOF Then WScript.Echo oRS.GetString(2, , "|", vbCrLf, "NULL")
oDB.Close
output:
6d5f1279d4deccbaeef5d074b13ed2f4|.\old\b\100_1608.jpg
26ff43419c4f30764fb015f6d7c869c1|.\old\b\100_1609.jpg
ADDED:
By using
Dim sSQL : sSQL = "SELECT O.*, N.PATH FROM [old.txt] O INNER JOIN [new.txt] N ON O.MD5 = N.MD5"
you could get the duplicates:
d95e29e2c0172dea438b12c418b09fd3|.\old\a\100_1610.jpg|.\new\c\100_1610.jpg
d95e29e2c0172dea438b12c418b09fd3|.\old\b\100_1610.jpg|.\new\c\100_1610.jpg
19f9cda002c951f7a9f870ce74fb1224|.\old\a\100_1601.jpg|.\new\c\100_1601.jpg
19f9cda002c951f7a9f870ce74fb1224|.\old\b\100_1601.jpg|.\new\c\100_1601.jpg
32b154f796303a8e9caff0c9d55ba713|.\old\a\100_1600.jpg|.\new\a\100_1600.jpg
32b154f796303a8e9caff0c9d55ba713|.\old\b\100_1600.jpg|.\new\a\100_1600.jpg
(cf. same approach, similar problem)
My code is as follows:
for /F "tokens=1,2 delims=%0.3%" %%i in ("double a = 0.3;") do (
set a=%%i
set b=%%j
)
I want a = "double a = " and b =";" but this code can not help.
Does anyone know how to solve this problem?
Your code as posted simply will not work at all.
for /F "tokens=1,2 delims=%0.3%" %%i in ("double a = 0.3;") do (
The %0 will be replaced by yourbatchfilename and since %" % has no value set in the environment, it will be replaced by [nothing] yielding
for /F "tokens=1,2 delims=yourbatchfilename.3i in ("double a = 0.3;") do (
which, unsurprisingly, is a syntax error.
#ECHO OFF
SETLOCAL
for /F "tokens=1,2 delims=3.0" %%i in ("double a = 0.3;") do (
set a=%%i
set b=%%j
)
ECHO first way :a=%a%+ b=%b%+
ENDLOCAL
SETLOCAL
SET "astring=double a = 0.3;"
SET "aseparator=0.3"
SET "arotorapes=3.0"
for /F "tokens=1,2 delims=%arotorapes%" %%i in ("double a = 0.3;") do (
SET a=%%i
)
CALL SET b=%%astring:*%aseparator%=%%
ECHO second way :a=%a%+ b=%b%+
ENDLOCAL
SETLOCAL
SET "astring=double a = 0.3;"
SET "aseparator=0.3"
CALL SET b=%%astring:*%aseparator%=%%
SET "c=%b%%aseparator%"
SET "a=%astring%"
:loop
IF DEFINED c SET c=%c:~0,-1%&SET a=%a:~0,-1%&GOTO loop
ECHO third way :a=%a%+ b=%b%+
In the first method, I've changed the sequence of the characters to deomstrate that any sequence of any of the characters between the = and " of a delims clause acts as a SINGLE delimiter. The code "works" by failing to fail.
In the second method, the setting of a works in the same way. Without further information, it's really not possible to tell whether this is adequate. b is set by specifically replacing all characters in the source string up to and including the separator with [nothing]
In the third method, the same operation establishes b, and then b and the separator are concatenated. Systematically lop off the characters at the end of a copy of the original original string and the concatenated string. When the concatenated version becomes empty, you've deleted the separator and the appendix from the original, leaving the portion of the original string up to the separator.
So I've been doing this with Notepad++ but it takes forever. I have a couple thousand files in a folder and need to add some text before and after every line in every file.
Is this even possible in command line?
For example this is a line:
This is my line.
And I want it to turn out like:
<text before>This is my line.<text after>
Any help would be appreciated!
Untested but should do the trick:
perl -pi -e 's/(.*)/<text before>$1<text after>/' *
The following pure native batch script will work, though it is relatively slow.
#echo off
setlocal disableDelayedExpansion
set "prefix=<text before>"
set "suffix=<text after>"
pushd "yourFolder"
for %%F in (*) do (
>"%%F.new" (
for /f "delims=" %%A in ('findstr /n "^" "%%F"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
echo !prefix!!ln:*:=!!suffix!
endlocal
)
)
move /y "%%F.new" "%%F" >nul
)
I have written a hybrid JScript/Batch script that can be used to very efficiently process text files. Using my REPL.BAT utility, the script could be as simple as:
#echo off
pushd "yourFolder"
for %%F in (*) do (
type "%%F" | repl "^(.*)" "<text before>$1<text after>" >"%%F.new"
move /y "%%F.new" "%%F" >nul
)
popd
The REPL.BAT script should be somewhere in your PATH.
Here is the REPL.BAT script. It is compatible with all modern Windows versions from XP onward. The utility is surprisingly powerful and easy to use, considering how little code there is. Nearly half the script consists of embedded documentation. The documentation can be viewed by typing REPL /? from the command prompt.
#if (#X)==(#Y) #end /* Harmless hybrid line that begins a JScript comment
::************ Documentation ***********
:::
:::REPL Search Replace [Options [SourceVar]]
:::REPL /?
:::
::: Performs a global search and replace operation on each line of input from
::: stdin and prints the result to stdout.
:::
::: Each parameter may be optionally enclosed by double quotes. The double
::: quotes are not considered part of the argument. The quotes are required
::: if the parameter contains a batch token delimiter like space, tab, comma,
::: semicolon. The quotes should also be used if the argument contains a
::: batch special character like &, |, etc. so that the special character
::: does not need to be escaped with ^.
:::
::: If called with a single argument of /? then prints help documentation
::: to stdout.
:::
::: Search - By default this is a case sensitive JScript (ECMA) regular
::: expression expressed as a string.
:::
::: JScript syntax documentation is available at
::: http://msdn.microsoft.com/en-us/library/ae5bf541(v=vs.80).aspx
:::
::: Replace - By default this is the string to be used as a replacement for
::: each found search expression. Full support is provided for
::: substituion patterns available to the JScript replace method.
::: A $ literal can be escaped as $$. An empty replacement string
::: must be represented as "".
:::
::: Replace substitution pattern syntax is documented at
::: http://msdn.microsoft.com/en-US/library/efy6s3e6(v=vs.80).aspx
:::
::: Options - An optional string of characters used to alter the behavior
::: of REPL. The option characters are case insensitive, and may
::: appear in any order.
:::
::: I - Makes the search case-insensitive.
:::
::: L - The Search is treated as a string literal instead of a
::: regular expression. Also, all $ found in Replace are
::: treated as $ literals.
:::
::: E - Search and Replace represent the name of environment
::: variables that contain the respective values. An undefined
::: variable is treated as an empty string.
:::
::: M - Multi-line mode. The entire contents of stdin is read and
::: processed in one pass instead of line by line. ^ anchors
::: the beginning of a line and $ anchors the end of a line.
:::
::: X - Enables extended substitution pattern syntax with support
::: for the following escape sequences:
:::
::: \\ - Backslash
::: \b - Backspace
::: \f - Formfeed
::: \n - Newline
::: \r - Carriage Return
::: \t - Horizontal Tab
::: \v - Vertical Tab
::: \xnn - Ascii (Latin 1) character expressed as 2 hex digits
::: \unnnn - Unicode character expressed as 4 hex digits
:::
::: Escape sequences are supported even when the L option is used.
:::
::: S - The source is read from an environment variable instead of
::: from stdin. The name of the source environment variable is
::: specified in the next argument after the option string.
:::
::************ Batch portion ***********
#echo off
if .%2 equ . (
if "%~1" equ "/?" (
findstr "^:::" "%~f0" | cscript //E:JScript //nologo "%~f0" "^:::" ""
exit /b 0
) else (
call :err "Insufficient arguments"
exit /b 1
)
)
echo(%~3|findstr /i "[^SMILEX]" >nul && (
call :err "Invalid option(s)"
exit /b 1
)
cscript //E:JScript //nologo "%~f0" %*
exit /b 0
:err
>&2 echo ERROR: %~1. Use REPL /? to get help.
exit /b
************* JScript portion **********/
var env=WScript.CreateObject("WScript.Shell").Environment("Process");
var args=WScript.Arguments;
var search=args.Item(0);
var replace=args.Item(1);
var options="g";
if (args.length>2) {
options+=args.Item(2).toLowerCase();
}
var multi=(options.indexOf("m")>=0);
var srcVar=(options.indexOf("s")>=0);
if (srcVar) {
options=options.replace(/s/g,"");
}
if (options.indexOf("e")>=0) {
options=options.replace(/e/g,"");
search=env(search);
replace=env(replace);
}
if (options.indexOf("l")>=0) {
options=options.replace(/l/g,"");
search=search.replace(/([.^$*+?()[{\\|])/g,"\\$1");
replace=replace.replace(/\$/g,"$$$$");
}
if (options.indexOf("x")>=0) {
options=options.replace(/x/g,"");
replace=replace.replace(/\\\\/g,"\\B");
replace=replace.replace(/\\b/g,"\b");
replace=replace.replace(/\\f/g,"\f");
replace=replace.replace(/\\n/g,"\n");
replace=replace.replace(/\\r/g,"\r");
replace=replace.replace(/\\t/g,"\t");
replace=replace.replace(/\\v/g,"\v");
replace=replace.replace(/\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}/g,
function($0,$1,$2){
return String.fromCharCode(parseInt("0x"+$0.substring(2)));
}
);
replace=replace.replace(/\\B/g,"\\");
}
var search=new RegExp(search,options);
if (srcVar) {
WScript.Stdout.Write(env(args.Item(3)).replace(search,replace));
} else {
while (!WScript.StdIn.AtEndOfStream) {
if (multi) {
WScript.Stdout.Write(WScript.StdIn.ReadAll().replace(search,replace));
} else {
WScript.Stdout.WriteLine(WScript.StdIn.ReadLine().replace(search,replace));
}
}
}