Word Sorting in Batch - sorting

Right let me rewrite this try to make it more clear.
Picture added to make this even clearer:
I have two files
File 1, contains words.
file 2, contains commands.
I need to put words from FILE 1
into FILE 2
I cannot copy-paste them one by one, because there is a LOT of words in FILE 1
File 1 is listed in alphabetical order (by first letter)
File 2 the command does not change
The issue is getting words from file 1 into file 2
but they have to be moved into quotes " " in file 2
so a script that could for example..
Take apple from file 1 and move it between quotes admin.executemotecommand "apple"inside file 2 as it goes down the list keeping the words in order as they move them across.
This could perhaps be done the same way around in which, the script writes the command in front of the words in file 1 as it goes down file 1's list
Is this even possible? I've never seen this done anywhere else and completely clueless if batch is even the right language for it.

The question is a little confusing, but based on your responses in the comments my understanding is that you don't necessarily need the script to edit a preexisting file 2, because you're repeating the same command(s) for each word, so the script can just create a new file based on the words in file 1.
You can do it at the prompt like this:
FOR /F %a IN (words.txt) DO ECHO admin.executeremotecommand "%a" >> commands.txt
The original version of the question indicated that you want more than one command for each word. I take it you changed that in order to simplify that question, and figured you'd just run the script once for each command? However, it's quite simple to have it produce more than one command for each word:
FOR /F %a IN (words.txt) DO (ECHO first.command "%a" & ECHO second.command "%a") >> commands.txt
In a batch file, you'd do it this way:
#ECHO OFF
FOR /F %%a IN (words.txt) DO (
ECHO first.command "%%a"
ECHO second.command "%%a"
) >> commands.txt
BTW, in the code in some of your comments, you surrounded the variable with %'s (%A%). That's incorrect; it would evaluate to the value of %A followed by a literal %. Surrounding with %'s is used only for environment variables. (Note that the %'s around environment variables do not get doubled in a batch file. For example, to get the current date, use ECHO %date% both at the prompt and in a batch file.)

Related

Script to move all files starting with the same 7 letters in a different folder named after first 7 chars of its future content

All files are in a directory (over 500 000 files), named in the following pattern
AR00001_1
AR00001_2
AR00001_3
AR00002_1
AR00002_2
AR00002_3
I need a script, can be both batch or unix shell that takes everything with AR00001 and moves it into a new folder that will be called AR00001, and does the same for AR00002 files etc
Here's what I've been trying to figure out until now
for f in *_*; do
DIR="$( echo ${f%.*} | tr '_' '/')"
mkdir -p "./$DIR"
mv "$f" "$DIR"
done
Thanks
// Update
Ran this in the CMD
for %F in (c:\test\*) do (md "d:\destination\%~nF"&move "%F" "d:\destination\%~nF\") >nul
Seems to be almost what I wanted, except that it does not take the first 7 characters as a substring but instead creates a folder for each file :/ I'm trying to mix it with your solutions
#echo off
setlocal enabledelayedexpansion
for %%a in (???????_*) do (
set "x=%%a"
set "x=!x:~0,7!"
md "!x!" >nul
move "!x!*" "!x!\" 2>nul
)
for every matching file do:
- get the first 7 characters
- create a folder with that name (ignore error message, if exist)
- move all files that start with those 7 characters (ignore errormessages, if files doesn't exist (already moved))
The following achieves the desired effect and checks for non-existence of the target directory each time before creating it.
#echo off
setlocal ENABLEDELAYEDEXPANSION
set "TOBASE=c:\target\"
set "MATCHFILESPEC=AR*"
for %%F in ("%MATCHFILESPEC%") do (
set "FILENAME=%%~nF"
set "TOFOLDER=%TOBASE%!FILENAME:~0,7!"
if not exist "!TOFOLDER!\" md "!TOFOLDER!"
move "%%F" "!TOFOLDER!" >nul
)
endlocal
In the move command, by moving only the current file rather than including a wildcard, we ensure that we're not eating up file names that might be about to appear the next time around the loop. Keeping it simple, assuming that efficiency is not of prime importance.
I'd recommend prototyping by creating batch files (with a .bat or .cmd extension) rather than trying to do complex tasks interactively using on one-liners. The behaviour can be different and there are more things you can do in a batch file, such as using setlocal to turn on delayed expansion of variables. It's also just a pain writing for loops using the %F interactively, only to have to remember to convert all those to %%F, %%~nF, etc. when pasting into a batch file for posterity.
One word of caution: with 500,000 files in the folder, and all of the files having very similar prefixes, if your file system has 8.3 directory naming turned on (which is often the default) it is possible to run into problems using wildcards. This happens as the 8.3 namespace gets more and more busy and there are fewer and fewer options for ways the file name can be encoded in 8 characters. (The hash table fills up and starts overflowing into unexpected file names).
One solution is to turn that feature off on the server but that may have severe implications for any legacy applications. To see what the file looks like in 8.3 naming scheme, you can do, e.g.:
dir /x /p AR*
... which might give you something like (where the left hand name is the one converted to 8.3):
ARB900~1.TST AR15467_RW322.tst
AR85E3~1.TST AR15468_RW322.tst
ARDDFE~1.TST AR15469_RW322.tst
AR1547~1.TST AR15470_RW322.tst
AR1547~2.TST AR15471_RW322.tst
...
In this example, since the first two characters seem to be maintained, there should be no conflict.
So for example if I say for %a in (AR8*) do #echo %a I get what might at first seem to be incorrect:
AR15468_RW322.tst
AR18565_RW322.tst
AR20376_RW322.tst
AR14569_RW322.tst
AR17278_RW322.tst
...
But this is actually correct; it is all the files that match AR8* in both the long file name and short file name formats.
Edit: I am aware in retrospect that this solution looks very similar to Stephan's, and I had browsed through the existing answers before starting work on my own, so I should credit him. I will try and save face by pointing out a benefit of Stephan's solution. Its use of wildcards should circumvent any 8.3 naming issue: by specifying the wildcard as ???????_*, it only catches the long file names and won't match any of the converted 8.3 file names (all of which are devoid of underscores in that position). Similarly, a wildcard such as AR?????_* would do the same.
With bash, you'd write:
for f in *; do
[[ -d $f ]] && continue # skip existing directories
prefix=${f:0:7} # substring of first 7 characters
mkdir -p "$prefix" # create the directory if it does not exist
mv "$f" "$prefix" # and move the file
done
For the substring expansion, see https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion -- this is probably the bit you're missing.

Copying files with specific extension from a list (text file) of directories

I have a text file with list of certain directories that I want to copy *.xlsx files from them to another directory.
This is how the the text file (list.txt) is arranged:
PT_NAK01, PT_NAK04, PT_NAK05, PT_JAR03
What I have so far:
#echo off
set main_folder="\\internal.company.com\project folder\"
set my_folder="C:\_M__\files"
for /f "tokens=*" %%i in (list.txt) DO (
xcopy "%main_folder%\%%i" "%my_folder%"
)
So the folders that I want to look into would be \\internal.company.com\project folder\PT_NAK01 etc.
What I don't know is how to pass the specific extension *.xlsx to this command.
Note: I haven't used /S switch with xcopy deliberately because I do not want the files in the sub-directories.
P.S. Solutions in powershell or cygwin work for me as well.
This is a cygwinshell answer (bash is an advanced shell that should be reserved for when standard Posix shell (/bin/sh) is insufficient). Note that slashes are reversed intentionally.
I see the format in your list.txt is delimited with commas and whitespace. I am going to assume that this is literal and the reason none of what you've tried so far works. Therefore, I am parsing it with the explicit assumption that comma and then space (, ) is a delimiter and that there is no way to escape them (e.g. if you have a file named apples, oranges.txt then my code would erroneously parse files named apples and oranges.txt).
#!/bin/sh
main_folder="${1:-//internal.company.com/project folder}"
my_folder="${2:-c:/_Masoud/files}"
cd "$main_folder" || exit $?
IFS=', ' find $(cat list.txt) -maxdepth 1 -name \*.xlsx |while IFS= read xlsx; do
mkdir -p "$my_folder/${xlsx%/*}"
cp -a "$xlsx" "$my_folder/$xlsx"
done
I've done some extra work for you to make this more abstract. $main_folder is taken from your first argument (a missing argument will default to //internal.company.com/project folder) and $my_folder is taken from your second argument (if missing, it defaults to c:/_Masoud/files). Don't forget to quote your command-line arguments if they contain spaces or interpretable characters.
After determining your source and destination, I then try to change directories to the source directory. If this fails, the script will stop with the same exit code.
Now for the loop. I've changed the Input Field Separator ($IFS) to be the comma and space (, ) we talked about earlier and then glued the contents of list.txt into its arguments, followed by the requirement of being one level deep (to include PT_NAK05/foobar/baz.xlsx, use -maxdepth 2 or just remove that clause altogether to view the file tree recursively), followed by the requirement of a name matching *.xlsx (this is escaped because your shell would otherwise assume you're talking about the local directory). The output of this is then read into a loop line by line as $xlsx. We recreate the target's parent directory in the new target destination if it's not already present, then we copy the file to that location. cp -a preserves permissions and time stamps.
One thing that made an error in my example was how I set the text file with the folder names. It should be set up with carriage return as separator instead of comma-separated entries.
PT_NAK01
PT_NAK04
PT_NAK05
etc.
With that, this batch-file (in reference to MatSnow's and shellter's comments) works fine for the purpose of the question.
#echo off
set main_folder="\\internal.company.com\project folder\"
set my_folder="C:\_M__\files"
for /f "tokens=*" %%i in (list.txt) DO (
xcopy "%main_folder%\%%i\*.xlsx" "%my_folder%"
)
Note: If you want to type this directly into the command line, you don't need double % for the variables.

Using a .bat file, I need to extract information after ")" punctuation from a variable and store it in another variable?

I have a variable from a text file.
set /p namz=<"playersname.txt"
Right now if I echoed this, it would echo the entire contents of the file.
The Contents of playersname.txt include the following,
theplayernameis:Player One
I need a code that I can use in .bat to help me to extract everything after the ":" from the .txt file while ignoring everything else before it, "Player One" then it needs to store it in another variable which I can call upon anytime I want it.
I've been racking my brain on this, trying to come up with a solution, been forum hopping for a long time, haven't quite found what I needed yet. Please help..
You have a single-line textfile, you need the second token after a delimiter that might be : or /:
for /f "tokens=2 delims=:/" %%a in (playersname.txt) do set namz=%%a
add every possible delimter to delims=

How to output multiple user input values into a single variable in BATCH using Windows 7?

SOLVED!
Update: It figures moments after posting for help which is something I never do I'd figure it out...I tend to over think things, and that was the case here, it was just so simple! >.<
Solution:
(This worked under Windows 7 Ultimate 64 Bit)
Set var=
Set var=SomeText %var1% %var2% %var3%
Echo %var% > output.txt
See an explanation in my answer below.
I've been searching and trying several posts here similar to my question for hours with no success. I'm not new to Programming in BATCH but I have memory problems and thus can't always remember things. It also doesn't help that I program in other languages on other platforms which usually means I'm trying to use *nix shell commands in my Windows Batch scripts >.<
I've gotten quite close with some examples but nothing that works as needed.
Ideally, I'd like this work to work on Windows 7, 8, 8.1, Vista and 10 as that is the intended target.
This is what I need to accomplish:
The user will answer a series of questions, each question is stored into a .txt file (or variable if you prefer. I just used text files because of a past project where I ran into issues with variables that couldn't be solved and text files worked). The lines in each text file will need to be output into a single text file, on a single line which will then be read back in as a variable and run. Again, you could just use and combine the variables in your example if that's easier for you or both of us ;P
This is a snippet example of how I was doing it
SET file1=
SET /P file1=file1:%=%
ECHO %file1% > file1.txt
Then
copy /b file1.txt + file2.txt + file3.txt + file4.txt output.txt
Here is how I'd like the result to look
toolkit /S "C:\ToolKit Bravo\Data\etc" "D:\ToolKit Bravo\Data\Ops"
The "" quotation marks are necessary. The output MUST be EXACTLY as shown above for the example I've given. The "/S" & paths are variable NOT fixed!
Here is the best I've been able to come up with using variables..
"toolkit /S "C:\ToolKit Bravo\Data\etc" "D:\ToolKit Bravo\Data\Ops""
Update 2 - An explanation as requested:
The paths in the above example directly above this are not fixed! This was an Example Only. "toolkit" is fixed, this doesn't change. "/S" is an option selected by the user to pass on to the "toolkit". Both the source and destination paths are again input by the user in "quotation" marks. They're not fixed paths.
As you can see the result is surrounded by quotations which is NOT acceptable. And Please remember, I NEED the quotations around the paths in the end result, so removing them all is NOT an option!
Any help is greatly appreciated! Thank you for your time.
Just take all of the characters between the quotes.
SET X="toolkit /S "C:\ToolKit Bravo\Data\etc" "D:\ToolKit Bravo\Data\Ops""
ECHO %X%
SET Y=%x:~1,-1%
ECHO %Y%
Solution:
This solved my problem under Windows 7 Ultimate 64 Bit
Set var=
Set var=SomeText %var1% %var2% %var3%
Echo %var% > textfile.txt
Using the SET command I first made sure the variable or var for short was empty. Using this command:
Set var=
I then proceeded to create my variable using all of the other variables I had created and wanted to combine using this line of code:
Set var=SomeText %var1% %var2% %var3%
Note that I have preceded the variables with "SomeText". This is where I'll place the name of the .exe I'm passing the arguments to, but it can be anything you want included. I also need spaces between each variable so I've left spaces between them in the example code. If you don't want the spaces simply remove them, and you'll have 1234, instead of 1 2 3 4.
Finally I send the combined variable out to a .txt file.
Echo %var% > textfile.txt
However, you could also simply call the new variable now like this:
%var%

How to renaming a lot of folders with a Windows batch file

I need change a lot of folders with a batch script file..
I have those format of name folders:
2013.03.12.08.05.06_Debug_Test1
2013.03.12.08.04.09_Debug_Test2
...
I need change for this:
2013.12.03.08.05.06_Debug_Test1
2013.12.03.08.04.09_Debug_Test2
Invert the number 12 with the number 03
This is possible using a windows batch file?
#echo off
for /f "tokens=1,2,3*delims=." %%a in ('dir /b /ad "*.*.*.*") do if not %%b==%%c echo ren "%%a.%%b.%%c.%%d" "%%a-%%c.%%b.%%d"
for /f "tokens=1,2,3*delims=.-" %%a in ('dir /b /ad "*-*.*.*") do if not %%b==%%c echo ren "%%a-%%b.%%c.%%d" "%%a.%%b.%%c.%%d"
Should get you started.
The first FOR selects directories of the format *.*.*.* and renames them *-*.*.* with the 2nd and 3rd elements swapped.
The second renames the renamed directories to change the - to .
Consider directories 2013.03.12.08.05.06_Debug_Test1 and 2013.12.03.08.05.06_Debug_Test1 - attempting to rename the one will fail because the other exists, hence need to rename twice.
(I've assumed that '-' does not exist in your directorynames - you may wish to substitute some other character - #,#,$,q suggest themselves)
Note that I've simply ECHOed the rename. Since the second rename depends on the first, the second set wouldn't be produced until the echo is removed from the first after careful checking.
I'd suggest you create a sample subdirectory to test first, including such names as I've highlighted.
Using StringSolver, which requires a valid JRE installation and sbt, allows to use a semi-automatic version of move:
move 2013.03.12.08.05.06_Debug_Test1 2013.12.03.08.05.06_Debug_Test1
Then check the transformation:
move --explain
concatenates for all a>=0 (a 2-digit number from the substring starting at the a+1-th number ending at the end of the a+1-th AlphaNumeric token in first input + the substring starting at the 2*a+2-th token not containing 0-9a-zA-Z ending at the end of the a+3-th non-number in first input) + the first input starting at the 4th AlphaNumeric token.
which means that it decomposed the transformation by:
2013.12.03.08.05.06_Debug_Test1
AAAABBBBAABCCCCCCCCCCCCCCCCCCCC
where
A is "a 2-digit number from the substring starting at the a+1-th number ending at the end of the a+1-th AlphaNumeric token in first input"
B is "the substring starting at the 2*a+2-th token not containing 0-9a-zA-Z ending at the end of the a+3-th non-number in first input"
C is "the first input starting at the 4th AlphaNumeric token."
which corresponds to what you expected for folders of this type.
If you do not trust it, you can have a dry run:
move --test
which displays what the mapping would do on all folders.
Then perform the transformation for all folders using move --auto or the abbreviated command
move
Alternative
Using the Monitor.ps1 modified and run in Powershell -Sta, you can do it yourself in Windows like in this Youtube video.
DISCLAIMER: I am a co-author of this software developped for academic purposes.

Resources