I'm looking for a random function in batch that I can tack onto the beginning of a filename. I'm creating several thousand symbolic links and I intend to randomize the sorted results by appending a random number to the beginning of the filename.
I have used this function in my nested for loops (iterating through all files in all subdirs):
mklink "%LINKDIR%\%random%%%f" "%%f"
It returns almost what I want. Unfortunately each symbolic link has the same starting random number. Is there anyway to reseed the %random% value?
Use delayed expansion. I.e. put
setlocal enabledelayedexpansion
at the start of your batch file and then use !random! instead of %random%. See help set for a detailed explanation of the topic.
The point here is that %random% gets expanded when the for loop is parsed; thus for subsequent iterations (i.e. when the loop is actually run) there is no variable there anymore, just the value. This is fixed by delayed expansion.
Related
So we have many CSV files which come from different salesmen at different times throughout the Day,
Each of these CSVs contain certain information with 1st Line as a header line,
a single Salesmen can send multiple CSVs which may have multiple entries(lines),
the CSVs which Belong to the same Salesman are differentatied by the Time Stamps which are followed by the Name of the Salesman in the CSV Filename
Eg.
ABC_XYZ_SMAN_05092019_1232.csv
ABC_XYZ_SMAN_05092019_1148.csv
ABC_XYZ_SMAN_05092019_1556.csv
Above Entries Belong to the Salesman ABC_XYZ
In the Same Directory there are other Salesman's CSVs also
Eg.
QWE_RTY_SMAN_05092019_1323.csv
QWE_RTY_SMAN_05092019_0845.csv
QWE_RTY_SMAN_05092019_2238.csv
Above Entries Belong to the Salesman QWE_RTY
Each of these files have Information With 1st line as Headers.
My Goal is to create merged CSV for each salesman with only a single header and delete all the CSVs which create the Merged CSVs.
So
ABC_XYZ_SMAN_05092019.csv
QWE_RTY_SMAN_05092019.csv
Would be the Output for the above Mentioned CSVs whith all the information and only one header on the 1st line.
all of this By using a Batch File.
Get the salesman as Token1 and Token2 and the rest of the filename as Token3.
Check, if a summary exists. If yes, copy only the data (without header), if no, copy the whole file (including header).
Then delete the file.
#echo off
for /f "tokens=1,2,* delims=_" %%a in ('dir /b /on *_sman_*') do (
if exist "%%a_%%b_merged.csv" (
more +1 "%%a_%%b_%%c" >>"%%a_%%b_merged.csv"
) else (
type "%%a_%%b_%%c" >"%%a_%%b_merged.csv"
)
del "%%a_%%b_%%c"
)
Note: the more +1 trick only works with a limited number of lines (IIRC about 64.000). If you hit that limit, make sure, the salesman gets a rise.
My line of code is:
SET /A 327761=%RANDOM% * 1000 / 32768 + 1
And I'm just getting a missing operator error. I don't see how this could be and other questions on here don't help.
Because nobody decided to post an answer, here it is, thanks to #SomethingDark
You can't have just numbers as variable names. So I added a character C to the start of the variable.
While it is a bad idea to name a variable starting with a number, the usual problem araises when trying to retrieve the value, not when you set it. That is, there is not any problem in doing
set "1234=some value"
You will have later problems retrieving the value because %1234% is parsed as %1 (first argument to batch file) followed by the string 234%
But as said, you can set the value. So, why something like set /a "1234=1+1" raises an error?
The reason is that the commands in cmd are first parsed to determine the command to execute, but in some cases, once the command has been identified, the rest of the work is delegated to a command specific parser. for command is one example of this behaviour, but set /a also has its own parser.
This set /a parser does not only handle the var=value syntax. You can also do things like
set /a 123+123
to retrieve the result of the calc not storing it anywhere.
The set /a parser handles its parameters as a sequence of numeric/arithmetic/logic/bit/assignment operands/operators. The = is just an assignment operator, and this operator needs the operand on its left side to be a variable name.
The problem is that the set /a parser gives precedence to the numeric operands over the variable names: if it starts with a number, it is a number operand. In your case, set /a 327761=...., the 327761 literal is handled as a numeric operand, not as a variable name, and the assignment operator can not assign a value to another value.
I'm trying to concatenate two binary files in Windows. The second of the two files is very large so I would like to avoid making a new file that is the concatenation of the two - instead, I would like the concatenation to appear in place, overwriting the larger file (hopefully this can also be faster?).
I tried the following:
copy /b mysmallfile.dat + mybigfile.dat mybigfile.dat
It asks if I want to overwrite mybigfile.dat, and when I say yes, mybigfile.dat now only contains the contents of mysmallfile.dat, rather than the concatenation of the two.
Very confusingly, if I try:
copy /b mybigfile.dat + mysmallfile.dat mybigfile.dat
It does not ask about overwriting, but does produce a file that is the concatenation of the two! However, the order is incorrect, I need the small file to be first in the concatenation.
I can't understand this behavior or how to get it to work. Any ideas? Thanks!
I'm making a program that changes coordinate values in a .gcd file, i got the single coordinate lines working but the lines with double coordinates aren't. The program is supposed to split the double coordinates up and run them separately as single coordinates. To accomplish this, I sort the form the coordinates could be in to different sections of code to give the right output. Using the length of the string I can sort them easily. While programming this I ran into a simple problem of a
IF " " LEQ " " ()
command. Given values it gets the wrong outcome. A good example is:
#echo off
:start
if "14" LEQ "7" goto next
echo this should be printed
pause
exit /b
:next
echo this shouldn't be printed
pause
exit /b
Removing the " " seems to fix the issue, but I need to compare variables, which can have spaces, justifying the parenthesis. So the question is:
Why does the interpreter get to the wrong outcome, and how can I easily fix this?
Thanks, -Tom
if "14" LEQ "7" goto next
This does a lexicographic string comparison, where "14" < "7" because the first non-equal character 1 < 7.
As you noted, if you drop the quotes the following will do a numerical comparison.
if 14 LEQ 7 goto next
This is consistent with the if /? help:
These comparisons are generic, in that if both string1 and string2 are both comprised of all numeric digits, then the strings are converted to numbers and a numeric comparison is performed.
The quote (which is part of the strings being compared in the first case) is not a numeric digit, so no conversion to numbers is performed, and the comparison is done on the strings by lexical rules.
You also say that but I need to compare variables, which can have spaces. However a numeric value does/can not contain spaces and does not require quotes. On the contrary, once enclosed in quotes it's no longer a numeric value, but a string. So you'll have to decide/distinguish in advance whether you want to compare numerical vs. string values.
In dos, when I wanted to get a list of files matching a specific filter, I could use something along the lines of:
*.* - Means return everything
*.txt - Means return all files with a .txt extension
*_abc.* - Means return every file that ends with _abc
My question is, using that dos filter structure, how could I return all files NOT matching *_abc.* (In other words, return all files whos name does NOT end in _abc)?
I don't remember if this is possible and I need this since a company I'm working with is using a very old program that still uses that form of command filtering for selecting files for the program to work on - Also, unfortunately, I can't do it via a batch command... It has to be a single command line statement.
Thanks!!!
Pipe the results of your listing to FINDSTR with an appropriate regex search string and the /V option to filter out matching lines.
dir /b /a-d * | findstr /v /r "_abc\.[^.]*$"
Take a look at this answer to a sort of unrelated question. The answer does show though how to do a REGEX search on file names, and of course if you use a REGEX you can easily search for things that don't match the expression.
https://stackoverflow.com/a/7381962/1246574
Hope that helps.
EDIT
Sorry, didn't see you needed it to be a single line statement and not a batch. I'll leave the above answer though in case it helps anyone else, and I'll also see if I can look up how to do it in a single statement.