Batch file move specific files - windows

I have a very large number of files with this template:
example1.part001.rar
example1.part002.rar
example1.part003.rar
...
example2.part001.rar
example2.part002.rar
example2.part003.rar
...
and sometimes with only two digits after "part"
example3.part01.rar
example3.part02.rar
example3.part03.rar
...
I'm trying to create a batch file that first makes n directories (n is for number of groups of files) with the name " example n ", and then that moves all relatives file into them.
I will explain better.
I have
cat.part01.rar
cat.part02.rar
cat.part03.rar
dog.part001.rar
dog.part002.rar
mouse.part01.rar
mouse.part02.rar
mouse.part03.rar
mouse.part04.rar
I want to first make the directories "cat", "dog" and "mouse, and then move all relatives file into them (I mean all "foldername.part*.rar in "foldername"), so "cat.part*.rar" files into "cat" folder and so on.
Files are many, and filenames are very very different and random.
Can somebody help me? Thanks

EDIT :
#echo off&cls
setlocal EnableDelayedExpansion
for %%a in (*.rar) do (set $file=%%~na
set $file=!$file:^.= !
call:work %%a)
exit /b
:work
for %%b in (!$file!) do (if not exist %%b md %%b
copy "%1" ".\%%b"
exit /b)

This should do it also, and handle filenames with ! in them too.
#echo off
for %%a in (*.rar) do (
if exist "%%a" for %%b in ("%%~na") do (
md "%%~nb" 2>nul
move "%%~nb.part*.rar" "%%~nb" >nul
)
)
pause

Here I get a list of groups by splitting the file name by '.'. I then get the uniq values of the first column. For each of the results I create the directory. Then move all files into the directory
#/usr/bin/sh
groupnames=(`ls *.rar | awk -F"." '{print $1}' | uniq`)
for i in ${groupnames[*]}; do
mkdir $i
mv $i.*.rar ./$i/
done

Example files of test:
ball.part1.rar
ball.part2.rar
cat.part01.rar
cat.part02.rar
dog.part001.rar
dog.part002.rar
The script creates folders ball, cat, dog, after that, it moves the files to their respective folders, works with partX, partXY and partXYZ in filename
#echo off
#break off
#title Batch file move specific files
#color 0a
#cls
setlocal EnableDelayedExpansion
if "%~1" NEQ "" (
set "WORKINGDIR=%~1"
) else (
set "WORKINGDIR=!CD!"
)
if not exist "!WORKINGDIR!\*.rar" (
set "WORKINGDIR=!CD!"
)
if not exist "!WORKINGDIR!\*.rar" (
echo There are no winrar files in this directory
echo.
echo Exiting...
echo.
ping -n 4 localhost>nul
pause
exit
)
for %%a in ( "!WORKINGDIR!\*.rar" ) do (
set "name=%%~nxa"
if "!name:~-4!" EQU ".rar" (
set "name=!name:~0,-4!"
)
if "!name:~-8,5!" EQU ".part" (
echo !name:~-7! | find ".">nul
if "!errorlevel!" NEQ "0" (
set "name=!name:~0,-8!"
) else (
set "skip=yes"
)
) else if "!name:~-7,5!" EQU ".part" (
echo !name:~-6! | find ".">nul
if "!errorlevel!" NEQ "0" (
set "name=!name:~0,-7!"
) else (
set "skip=yes"
)
) else if "!name:~-6,5!" EQU ".part" (
echo !name:~-5! | find ".">nul
if "!errorlevel!" NEQ "0" (
set "name=!name:~0,-6!"
) else (
set "skip=yes"
)
)
if not defined skip (
set "skip=no"
)
if "!skip!" EQU "no" (
if not exist "!WORKINGDIR!\!name!\" (
mkdir "!WORKINGDIR!\!name!\"
)
move /y "!WORKINGDIR!\%%~nxa" "!WORKINGDIR!\!name!\%%~nxa"
)
set "skip=no"
)
pause
exit

Related

How to split string with windows batch

I have a code that creates a bulk folder for each file and drags the file into the corresponding folder, but I am trying to shorten (split) the string.
For example, convert
L2021-56378 Sample Documentation Form
L2022-56378 Sample Documentation Form
L2023-56378 Sample Documentation Form
to just
L2021-56378
L2022-56378
L2023-56378
Below is my code:
#echo off
for %%i in (*) do (
if not "%%~ni" == "organize" (
md "%%~ni" && move "%%~i" "%%~ni"
)
)
...
if not "%%~ni" == "organize" (
for /f %%e in ("%%~ni") do (
ECHO %%e
ECHO md "%%e" 2>nul&& ECHO move "%%~i" "%%e"
)
)
...
should do that - I'm assuming you want a directory named L2021-56378 and to move the file to that directory.
The ECHO keywords are present to report the intended operations to the screen for verification. Remove them if the commands are correct to actually do the md and move.
See for /? from the prompt or many, many items on SO for documentation. The for/f uses default options tokens=1 and delims includes Space
----- Applying this to your code,
#echo off
for %%i in (*) do (
if not "%%~ni" == "organize" (
for /f %%e in ("%%~ni") do (
ECHO %%e
ECHO md "%%e" 2>nul&& ECHO move "%%~i" "%%e"
)
)
)
works for me.

Create a .bat file based on common column and out put will be selective column

I am completely new to .bat code. I want to merge two csv file based on common column and selective columns for the output file.
For ex
file1.csv
id,name,roll
1,x,12
2,y,13
file2.csv
id,class,subject
1,V,english
2,III,Math
Output will be
result.csv
id,name,class,subject
1,x,V,english
2,y,III,Math
Below is the code I started. My problem is how to use the common column and select the column.
#echo off
set "tmpfile=%temp%\result.tmp"
set "csvfile=result.csv"
copy nul "%tmpfile%" >nul
echo.
echo Processing all CSV files...
set "header="
for %%a in (%1) do (
if not "%%a"=="%csvfile%" (
set /p =Processing %%a...<nul
for /f "tokens=1* usebackq delims=," %%b in ("%%a") do (
if /i "%%b"=="Keyword" (
if not defined header (
set /p =Found header...<nul
set "header=%%b,%%c"
)
) else (
title [%%a] - %%b,%%c
findstr /b /c:"%%b" /i "%tmpfile%">nul || echo %%b,%%c>>"%tmpfile%"
)
)
echo OK
)
)
echo Finished processing all CSV files
echo.
echo Creating %csvfile%
echo %header%>"%csvfile%"
set /p =Sorting data...<nul
sort "%tmpfile%">>"%csvfile%"
echo OK
del "%tmpfile%"
echo Finished!
title Command Prompt
exit /b
The problem description lacks multiple details and the example code provided has no relation to the description. In the description you talk about two files but in the code you process "all CVS files" with no indication of which "two files" should be merged. The code has an undescribed "Keyword" value. The code sorts the output file, but this is not necessary because "both input files are sorted by common column" as you said...
Anyway I tried to help you writting a working code that achieve what you said in the problem description. I searched for "file merge" in the Batch-file tag and get multiple results, so I just used this method as base...
#echo off
setlocal EnableDelayedExpansion
set "Header1="
set "Header2="
set "common2=-999999999"
rem Read second file from redirected input
< file2.csv (
rem Read first file via FOR /F
for /F "tokens=1,2 delims=," %%a in (file1.csv) do (
if not defined Header1 (
set "Header1=%%a,%%b"
) else (
if !common2! lss %%a call :ReadNextFile2RecordUntil %%a
if !common2! equ %%a echo %%a,%%b,!rest2!
)
)
) > result.csv
goto :EOF
:ReadNextFile2RecordUntil commonCol
set "line2="
set /P "line2="
if not defined line2 set "common2=999999999" & exit /B
for /F "tokens=1* delims=," %%A in ("%line2%") do (
if not defined Header2 (
set "Header2=%%B"
echo %Header1%,%%B
goto ReadNextFile2RecordUntil %1
) else (
set "common2=%%A"
set "rest2=%%B"
)
)
if !common2! lss %1 goto ReadNextFile2RecordUntil %1
exit /B
file1:
id,name,roll
1,x,12
2,y,13
4,z,record1 with no matching record2
5,t,15
file2.csv:
id,class,subject
1,V,english
2,III,Math
3,IV,record2 with no matching record1
5,V,OK
result.csv:
id,name,class,subject
1,x,V,english
2,y,III,Math
5,t,V,OK

count number of rows per text file using batch file

I have this batch command that counts the number rows per log/text file. If I have a text file that has 3 or more rows meaning my md5deep verification has a mismatch. The problem is I have multiple folders with CheckMismatch.txt. I am looking for a looping that will CHECK all CheckMismatch.txt and count the rows one by one.
IF EXIST C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1 (md5deep64 -x "C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1\FOLDER1.md5" -r "C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1" > C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1\CheckMismatch.txt
#echo off
setlocal EnableDelayedExpansion
set "cmd=findstr /R /N "^^" C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1\CheckMismatch.txt | find /C ":""
for /f %%a in ('!cmd!') do set number=%%a
if %number% gtr 2 (echo there is a mismatch in FOLDER1) ELSE (echo FOLDER1 HASHES matched)
)
Folder1
CheckMismatch.txt
Folder2
CheckMismatch.txt
Folder3
CheckMismatch.txt
Folder4
CheckMismatch.txt
Folder5
CheckMismatch.txt
There is no need for FINDSTR before FIND. You can count the rows directly with FIND alone. And you can use FINDSTR to test if the count is less than or equal to 2. This enables you to use && and || instead of IF.
If you want to process a fixed list of folders under "C:\BACKUPS\WEBAPP-UAT\WEBAPP\"
#echo off
setlocal
set "root=C:\BACKUPS\WEBAPP-UAT\WEBAPP"
for %%F in (
Folder1
Folder2
Folder3
Folder4
Folder5
) do (
md5deep64 -x "%root%\%%F\%%F.md5" -r "%root%\%%F" >"%root%\%%F\CheckMismatch.txt"
type "%root%\%%F\CheckMismatch.txt" | find /c /v "" | findstr /x "0 1 2" && (
echo There is a mismatch in %%F
) || (
echo %%F hashes matched
)
)
It is more likely that you want to process all folders under "C:\BACKUPS\WEBAPP-UAT\WEBAPP\"
#echo off
for /d %%F in ("C:\BACKUPS\WEBAPP-UAT\WEBAPP\*") do (
md5deep64 -x "%%F\%%~nxF.md5" -r "%%F" >"%%F\CheckMismatch.txt"
type "%%F\CheckMismatch.txt" | find /c /v "" | findstr /x "0 1 2" && (
echo %%~nxF hashes matched
) || (
echo There is a mismatch in %%~nxF
)
)
If CheckMismatch.txt is just a temporary file that you don't need later on, then you can avoid creation of the file entirely
#echo off
for /d %%F in ("C:\BACKUPS\WEBAPP-UAT\WEBAPP\*") do (
md5deep64 -x "%%F\%%~nxF.md5" -r "%%F" | find /c /v "" | findstr /x "0 1 2" && (
echo %%~nxF hashes matched
) || (
echo There is a mismatch in %%~nxF
)
)
There was a delayed expansion problem (using %number% in a code block instead of !number!)
Tried to format more clearly.
#Echo off
SetLocal EnableExtensions EnableDelayedExpansion
Set "Folder=C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1
IF EXIST "%Folder%" (
md5deep64 -x "%Folder%\FOLDER1.md5" ^
-r "%Folder%" > "%Folder%\CheckMismatch.txt"
set "cmd=findstr /R /N "^^" "%Folder%\CheckMismatch.txt" | find /C ":""
Set "number=0"
for /f %%a in ('!cmd!') do set number=%%a
if !number! gtr 2 (
echo there is a mismatch in FOLDER1
) ELSE (
echo FOLDER1 HASHES matched)
)
)

Trouble getting a moving script to read filename and perform actions based on this

I am trying to get a mover batch script to read the filenames in a folder and do things to them based on the filename before moving them.
I have no trouble getting the files to be moved but I can't get the doing stuff based on filename part right.
#ECHO on
setlocal enableDelayedExpansion
SET src_folder=c:\recordz
SET tar_folder=\\TOWER\Temprec
:LOOP
for /f "delims=" %%a IN ('dir "%src_folder%"\*.mpg /b') do (
set "var=%%~na"
Echo %var%
Rem this part is supposed to check if NFL is part of the filename
If NOT "%var%"=="%var:NFL=%" (
echo Found inside
REN "%src_folder%\%%~na.mpg" "%%~na.ts"
move %src_folder%\"%%~na.ts" %tar_folder%
) else (
echo No cigar
move %src_folder%\"%%~na.mpg" %tar_folder%
)
)
REM Crafty 5 minute delay...
PING 1.1.1.1 -n 1 -w 1800000 >NUL
GOTO LOOP
When I run the above, I get this:
C:\Scripts>(
set "var=Feux_20161003_21002200"
Echo
If NOT "" == "NFL=" (
echo Found inside
REN "c:\recordz\Feux_20161003_21002200.mpg" "Feux_20161003_21002200.ts"
move c:\recordz\"Feux_20161003_21002200.ts" \\TOWER\Temprec
) else (
echo No cigar
move c:\recordz\"Feux_20161003_21002200.mpg" \\TOWER\Temprec
)
)
ECHO is on.
Found inside
Although you have enabled the delayed expansion you are not using it. Change % to ! inside the loop.
for /f "delims=" %%a IN ('dir "%src_folder%"\*.mpg /b') do (
set var=%%~na
Echo !var!
Rem this part is supposed to check if NFL is part of the filename
If NOT "!var!"=="!var:NFL=!" (
echo Found inside
REN "%src_folder%\%%~na.mpg" "%%~na.ts"
move %src_folder%\"%%~na.ts" %tar_folder%
) else (
echo No cigar
move %src_folder%\"%%~na.mpg" %tar_folder%
)
)

Windows batch file to list all duplicates (and the original file) in tree and sort them

I have to check a tree for duplicating files and write all of them to List.txt file.
But my script seems to skip one of the file locations in each group. (For example, if there are 4 duplicating files, only 3 of them appear in the list.)
If I'm not mistaken, it's the location of the "previousFile" of the last comparison that is missing. How do I write it to the list, too?
Also, how can I group paths in the List.txt by the filename so that it looks something like this:
File fileNameA.txt :
C:\path1\fileNameA.txt
C:\path2\fileNameA.txt
C:\path3\fileNameA.txt
File fileNameB.txt :
C:\path1\fileNameB.txt
C:\path2\fileNameB.txt
C:\path3\fileNameB.txt
C:\path4\fileNameB.txt
File fileNameC.txt :
C:\path1\fileNameC.txt
C:\path2\fileNameC.txt
...
?
That's my script so far:
#echo off
setlocal disableDelayedExpansion
set root=%1
IF EXIST List.txt del /F List.txt
set "prevTest=none"
set "prevFile=none"
for /f "tokens=1-3 delims=:" %%A in (
'"(for /r "%root%" %%F in (*) do #echo %%~zF:%%~fF:)|sort"'
) do (
set "currentTest=%%A"
set "currentFile=%%B:%%C"
setlocal enableDelayedExpansion
set "match="
if !currentTest! equ !previousTest! fc /b "!previousFile!" "!currentFile!" >nul && set match=1
if defined match (
echo File "!currentFile!" >> List.txt
endlocal
) else (
endlocal
set "previousTest=%%A"
set "previousFile=%%B:%%C"
)
)
You need to count matches and add echo previous filename to echo current one in case of the first match.
Note '"(for /r "%root%" %%F in (*) do #echo(%%~nxF?%%~zF?%%~fF?)|sort"' changes:
used ? (question mark) as a delimiter: reserved character by Naming Files, Paths, and Namespaces
added %%~nxF? prefix to sort output properly by file names even in my sloppy test folder structure, see sample output below.
This output shows than even cmd poisonous characters (like &, %, ! etc.) in file names are handled properly with DisableDelayedExpansion kept.
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "root=%~1"
if not defined root set "root=%CD%"
set "previousTest="
set "previousFile="
set "previousName="
set "match=0"
for /f "tokens=1-3 delims=?" %%A in (
'"(for /r "%root%" %%F in (*) do #echo(%%~nxF?%%~zF?%%~fF?x)|sort"'
) do (
set "currentName=%%A"
set "currentTest=%%B"
set "currentFile=%%C"
Call :CompareFiles
)
ENDLOCAL
goto :eof
:CompareFiles
if /I "%currentName%" equ "%previousName%" ( set /A "match+=1" ) else ( set "match=0" )
if %match% GEQ 1 (
if %match% EQU 1 echo FILE "%previousFile%" %previousTest%
echo "%currentFile%" %currentTest%
) else (
set "previousName=%currentName%"
set "previousTest=%currentTest%"
set "previousFile=%currentFile%"
)
goto :eof
Above script lists all files of duplicated names regardless of their size and content. Sample output:
FILE "d:\bat\cliPars\cliParser.bat" 1078
"d:\bat\files\cliparser.bat" 12303
"d:\bat\Unusual Names\cliparser.bat" 12405
"d:\bat\cliparser.bat" 335
FILE "d:\bat\Stack33721424\BÄaá^ cčD%OS%Ď%%OS%%(%1!)&°~%%G!^%~2.foo~bar.txt" 120
"d:\bat\Unusual Names\BÄaá^ cčD%OS%Ď%%OS%%(%1!)&°~%%G!^%~2.foo~bar.txt" 120
To list all files of duplicated names with the same size but regardless of their content:
:CompareFiles
REM if /I "%currentName%" equ "%previousName%" (
if /I "%currentTest%%currentName%" equ "%previousTest%%previousName%" (
set /A "match+=1"
REM fc /b "%previousFile%" "%currentFile%" >nul && set /A "match+=1"
) else ( set "match=0" )
To list all files of duplicated names with the same size and binary content:
:CompareFiles
REM if /I "%currentName%" equ "%previousName%" (
if /I "%currentTest%%currentName%" equ "%previousTest%%previousName%" (
REM set /A "match+=1"
fc /b "%previousFile%" "%currentFile%" >nul && set /A "match+=1"
) else ( set "match=0" )
Edit If the name of the file doesn't matter (only its contents), you could apply next changes in FOR loop and in :CompareFiles subroutine:
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "root=%~1"
if not defined root set "root=%CD%"
set "previousTest="
set "previousFile="
set "match=0"
for /f "tokens=1-2 delims=?" %%A in (
'"(for /r "%root%" %%F in (*) do #echo(%%~zF?%%~fF?)|sort"'
) do (
set "currentTest=%%A"
set "currentFile=%%B"
rem optional: skip all files of zero length
if %%A GTR 0 Call :CompareFiles
)
ENDLOCAL
goto :eof
:CompareFiles
if /I "%currentTest%" equ "%previousTest%" (
fc /b "%previousFile%" "%currentFile%" >nul && set /A "match+=1"
) else ( set "match=0" )
if %match% GEQ 1 (
if %match% EQU 1 echo FILE "%previousFile%" %previousTest%
echo "%currentFile%" %currentTest%
) else (
set "previousTest=%currentTest%"
set "previousFile=%currentFile%"
)
goto :eof

Resources