Delete duplicate top-level folder names from list with batch - batch-file

I need to delete duplicate folder names from a folder list. The duplicates occur when there's more than 1 subfolder. I end up with a list like below. I want to get rid of any line that has a sub2 folder.
folder1\sub1
folder2\sub1
folder2\sub1\sub2
folder3\sub1
Following code works if there is only one sub2 foldername, but it's awkward--hopeless if more than one sub2. There's gotta be a better way. Any help much appreciated.
#Echo off
SETLOCAL EnableDelayedExpansion
:: Write the sub2 foldernames to a tmp file
For /f "tokens=3 delims=\" %%I IN (folderlist.txt) DO Echo %%I >>temp.tmp
:: Set var for each sub2 name in tmp file and
:: call routine to write lines that don't contain that name
For /f %%G in (temp.tmp) do (
Set findstring=%%G
CALL :FindDup
)
EXIT
:findDup
For /f %%H in ('Type folderlist.txt ^|Find "!findstring!" /v') Do (
Echo %%H >> NoDup.txt
)
exit /b
FWIW: I'm using this command to generate the list, then deleting the path preceding folder1, folder2, etc
For /d %%G in (*) do dir /ad /on /s /b "%%G" >> folderlist.txt

you are almost there, if you just want the resulting list after eliminating the subfolders, just try to echo the appropiate lines to the list file, having copied it first into a temporary.
move folderlist.txt %temp%\folders.txt
for /f "tokens=1,2,* delims=\" %%a in (%temp%\folders.txt) do (
if .%%c==. echo %%a\%%b >>folderlist.txt
)
if you want to remove the folder from the disk, then change the line to
if not .%%c==. rd /s %%a\%%b\%%c

#ECHO OFF
SETLOCAL
FOR /f "delims=" %%a IN (q20840158.txt) DO (
FOR /f "tokens=1,3delims=\" %%b IN ("%%a") DO IF "%%c"=="" ECHO(%%a
)
GOTO :EOF
I used a file named q20840158.txt containing your data for my testing.
But - It's really unclear what you mean by a "duplicate". How precisely do you define a duplicate in this context?

#ECHO OFF
SETLOCAL
COPY NUL newfile.txt >NUL 2>nul
FOR /f "delims=" %%a IN (q20840158.txt) DO (
ECHO %%a|FINDSTR /I /L /g:"newfile.txt" >NUL 2>NUL
IF ERRORLEVEL 1 >>"newfile.txt" ECHO(%%a
)
TYPE newfile.txt
GOTO :EOF
I used a file named q20840158.txt containing your data for my testing.
Produces newfile.txt
Ah- you want to make sure that any additions to the list don't contain a previous entry...

Related

How to insert a revision number in string

I’m using the following script to add a revision number to a .stp file. For example: ABS0012033.stp to ABS0012033_rev001.stp. This is working well.
Now I have some files that end with _asm.stp, for example, ABS0012033_asm.stp. How do I need to modify the script that it works for both file types?
Some additional information: There is only one .stp file to be renamed per time and then the .stp file will be moved to another folder. The text file which contains the revision number is temporary and will be deleted after renaming the .stp file.
The current script does remove the last 4 characters from the filename and stores the filename in variable str1. Then it renames the filename with str1 + revision number.
for /F "usebackq tokens=2" %%a IN (`findstr REVISION C:\PUBLISH_WORKSPACE\*.txt`) do (
SET Rev=%%a)
FOR %%S IN ( c:\publish_workspace\*.STP) DO (SET FILE=%%S)
set str1=%file:~21,-4%
ren %file% %str1%_rev%REV%.stp
EXIT
I have tried to implement an IF function in the following script, but it doesn’t work. It doesn’t write str1 when renaming the filename. Any ideas what the problem could be?
for /F "usebackq tokens=2" %%a IN (`findstr REVISION C:\PUBLISH_WORKSPACE\*.txt`) do (
SET Rev=%%a)
FOR %%S IN ( c:\publish_workspace\*.STP) DO (SET FILE=%%S)
echo.%FILE%|findstr /C:"_asm" >nul 2>&1
if not errorlevel 1 (
set str1=%file:~21,-8%
ren %file% %str1%_rev%REV%.stp
) else (
set str1=%file:~21,-4%
ren %file% %str1%_rex%REV%.stp
)
pause
move c:\publish_workspace\*.stp c:\publish_workspace\stp
del c:\publish_workspace\*.txt
EXIT
Sorry, I'm not sure to understand the problem. What about this?
set Rev=ren001
ren ABS???????_asm.stp ABS???????_%Rev%.stp
This answer makes assumptions, those assumptions could have been resolved had you responded to my comment one day ago.
#Echo Off & SetLocal EnableExtensions
PushD "C:\Publish_Workspace" 2>NUL && (Set "Rev=") || GoTo :EOF
For /F "Tokens=1,* Delims=:" %%G In ('%SystemRoot%\System32\findstr.exe "REVISION" "*.txt"') Do Set "Rev=%%H"
If Not Defined Rev GoTo :EOF
For /F Delims^=^ EOL^= %%G In ('Set "PathExt=" ^& %SystemRoot%\System32\where.exe ".":"*.stp" 2^>NUL') Do For /F Delims^=_^ EOL^= %%H In ("%%~nG") Do Ren "%%G" "%%H_rev%Rev:* =%%%~xG"
I am not a tutor, and will not be providing additional explanation, other than to refer you to my comments, and the built-in help information for each command, (commandName /?).

Batch folder creation based on part of file name, without keeping extension

Trying to create a script that will take the third token of a file name, create a folder based on it and move the associated file to that folder.
Have got this so far:
#ECHO OFF
SETLOCAL
SET "sourcedir=D:\Sourcedir"
PUSHD %sourcedir%
FOR /f "tokens=1,2,3,4 delims=" %%a IN (
'dir /b /a-d "*.pdf"'
) DO (
ECHO MD %%c
ECHO MOVE "%%a %%b %%c %%d" .\%%c\
)
POPD
GOTO :EOF
Only problem is the folder being created is including the file extension where as I just need the folder to be named the third token.
Example file name:
"File Number 10.pdf
Expected folder name:
10
Thanks
Why did you use delims=? This will remove delimiter, and take whole line to %%a.
Try this:
#ECHO OFF
SETLOCAL
SET "sourcedir=D:\Sourcedir"
PUSHD %sourcedir%
FOR /f "tokens=1,2,3" %%a IN (
'dir /b /a-d "*.pdf"'
) DO (
ECHO MD %%~nc
ECHO MOVE "%%a %%b %%c" .\%%~nc\
)
POPD
GOTO :EOF
When no delims= set, it will use space. So %%c will be 10.pdf, ~n is to extract its name part.
This is based on your question, which you can concatenate %%a %%b %%c together with spaces, then it's simple.
If your filenames are more complicated, then an inner for loop is better.
-- Which another question already gave a great solution.
Here's an alternative, which will just use the last space delimited string/number, regardless of how many there are, (if there are none it will use the whole filename)!
#Echo Off
For %%A In ("D:\Sourcedir\*.pdf") Do Call :L "%%A"
Exit /B
:L
Set "F=%~n1"
Set "F=%F: ="&Set "F=%"
If Not Exist "%~dp1%F%\" MD "%~dp1%F%"
Move /Y %1 "%~dp1%F%"
And if you wanted to move only those which have at least one space, you can include that inside the For parentheses.
#Echo Off
For %%A In ("D:\Sourcedir\* *.pdf") Do Call :L "%%A"
Exit /B
:L
Set "F=%~n1"
Set "F=%F: ="&Set "F=%"
If Not Exist "%~dp1%F%\" MD "%~dp1%F%"
Move /Y %1 "%~dp1%F%"
You can run 2 for loops get the full name in the first, then split the name in the second loop, get the 3rd token, create the directory and then copy the actual file name from the first loop.
This way you do not need to try and patch the name together again, I know it works, but it is ugly and not prefered:
#echo off
setlocal enabledelayedexpansion
set "sourcedir=D:\Sourcedir"
pushd %sourcedir%
for %%a in (*.pdf) do (
set "var=%%a"
for /f "tokens=3" %%i in ("!var!") do (
echo md "%%~ni"
echo move "%%~a" "%%~ni"
)
)
popd
goto EOF
For more information on these commands, see help for each from cmd.exe i.e
for /?
set /?
setlocal /?
set and setlocal has very specific information regarding delayed expansion.

Batch script to delete files in folder that does not contain certain word

I am new to batch scripting . I need to delete all files in a folder that DOES NOT contains some word in the file
found this code
#echo off
setlocal
pushd C:\Users\admin\Desktop\bat
findstr /ip /c:"importantWord" *.txt > results.txt
popd
endlocal
So how i can WHITE list this files, and delete all other?
Or i think there is easy way with just check if !contains and delete
but i don`t know how?
Supposedly, this problem could be solved in a very simple way combining these findstr switches: /V that show results when the search string is not found, and /M that show just the name of the files; that is:
#echo off
setlocal
cd C:\Users\admin\Desktop\bat
for /F "delims=" %%a in ('findstr /ipvm /c:"importantWord" *.txt') do del "%%a"
Unfortunately, the combination of /V and /M switches don't properly work: the result of /V is based on lines (not files), so a modification in the method is needed:
#echo off
setlocal
cd C:\Users\admin\Desktop\bat
rem Create an array with all files
for %%a in (*.txt) do set "file[%%a]=1"
rem Remove files to preserve from the array
for /F "delims=" %%a in ('findstr /ipm /c:"importantWord" *.txt') do set "file[%%a]="
rem Delete remaining files
for /F "tokens=2 delims=[]" %%a in ('set file[') do del "%%a"
This method is efficient, particularly with big files, because findstr command report just the name of the files and stop searching after the first string match.
#echo off
setlocal
set "targetdir=C:\Users\admin\Desktop\bat"
pushd %targetdir%
for /f "delims=" %%a in ('dir /b /a-d *.txt') do (
findstr /i /p /v /c:"importantWord" "%%a" >nul
if not errorlevel 1 echo del "%%a"
)
popd
endlocal
Not really sure what you want to do with /pfiles - files containing non-ansi characters appear to return errorlevel 1for these. if not errorlevel 1 will echo the files that do not contain the required string - remove the echo to actually delete the file(s)
This should work:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
SET "pathToFolder=C:\FolderToEmpty"
SET "wordToSearch=ImportantWord"
FOR /F "tokens=*" %%F IN ('dir %pathToFolder% /b *.txt') DO (
findstr /IP %wordToSearch% "%pathToFolder%\%%F">nul
IF !ERRORLEVEL!==1 (
DEL /Q "%pathToFolder%\%%F"
)
)
You will have to set the proper path to the folder you want to delete the files from and to replace ImportantWord with the substring you are looking for.

Batch file for counting the files with same initial name and moving them

Is it possible to do this?
In a folder i have files with same initial names
Example:
Main folder
-Quest2323231.txt
Quest2343434.txt
Quest2343435.txt
Fund103.txt
Fund102.txt
I have a config file (abc.config) in which i have name of file on which i need to count and move them . If the count is more than 2 then i need to move them.
In this case for e g I need to find files which have name as 'Quest'
Appreciate you help on this.
#echo off
setlocal enableextensions
set "number="
for /f "tokens=1" %%a in (
'dir /a-d /-c "c:\mainfolder\quest*" 2^>nul^|findstr /b /c:" "'
) do if not defined number set "number=%%a"
if not defined number set "number=0"
echo %number%
Untested: This expects text in the first line of abc.config which is the file information such as Quest in the example and if there are more than 2 matching files in the source folder then it will echo a move command to move them to the target folder.
Change *%file%* to %file%* in two places if you want to match only the start of the filename.
Remove the echo to actually perform the move commands.
#echo off
set "source=c:\mainfolder"
set "target=d:\target\folder"
set /p "file=" < "abc.config"
for /f %%a in ('dir /b /a-d "%source%\*%file%*" ^|find /i "%file%" 2^>nul^|find /c /v "" ') do set "number=%%a"
if %number% GTR 2 for /f "delims=" %%a in ('dir /b /a-d "%source%\*%file%*" ^|find /i "%file%" ') do (
echo move "%source%\%%a" "%target%"
)
pause

Batch Script to Delete Files with Unique Root Stem in Directory

Is it possible to write a batch file that deletes all files in a directory for which the first n characters of the file's root name do not match the first n characters of any other filenames in that directory? For instance, suppose the directory contains the following:
Purcell_HenryA.txt
Purcell_HenryB.txt
Casaubon_IsaacA.txt
In this case, we would want to delete all files in the directory whose first 13 characters did not match the first 13 characters in any other files in the directory. (That is, we'd want to delete only Casaubon_IsaacA.txt.) I have tracked down scripts that delete all files with unique extensions in a directory, but don't know how to begin to write this script, and would therefore be grateful for any leads on the question.
This checks for root filenames of 14 characters and over - and if there is only 1 file with the same leading 13 characters then it will echo del. Remove the echo to make it perform the deletion.
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%a in ('dir /b /a-d') do (
set "part=%%~na"
if not "!part:~13,1!"=="" (
set "part=!part:~0,13!"
for /f "delims=" %%b in ('dir /b /a-d "!part!*.*" ^|find /c "!part!" ') do (
if %%b EQU 1 echo del "%%a"
)
)
)
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET target=u:\testdir
DIR /b /a-d %target%
echo====^^ names IN DIR ^^===
SET length=13
SET match=:
SET "candidate="
FOR /f "delims=" %%i IN ('dir /b/a-d "%target%\*"') DO (
SET filename=%%i
SET section=!filename:~0,%length%!
IF !section!==!match! (SET "candidate=") ELSE (
IF DEFINED candidate ECHO(DEL %target%\!candidate!
SET candidate=%%i
SET match=!section!
)
)
IF DEFINED candidate ECHO(DEL %target%\!candidate!
GOTO :EOF
Test result:
abc123_uniquename.txt
another_uniquename.txt
duplicate_name1234.txt
duplicate_name1235.txt
duplicate_name1236.txt
hello.txt
repeated__name1236.txt
repeated__name1235.txt
unique__name1235.txt
===^ names IN DIR ^===
DEL u:\testdir\abc123_uniquename.txt
DEL u:\testdir\another_uniquename.txt
DEL u:\testdir\hello.txt
DEL u:\testdir\unique__name1235.txt
If you are happy after testing, remove both ECHO( to activate the delete function.
For this code file name = name+extension:
#echo off &SETLOCAL enabledelayedexpansion
FOR %%a IN (*) DO (
SET "search=%%~a"
IF "!search:~13!" neq "" (
FOR /f "delims=[]" %%b IN ('dir /b /a-d /on "!search:~0,13!*" ^| find /n "!search:~0,13!"') DO SET found=%%b
IF !found! equ 1 ECHO DEL "%%~a"
)
)
And because I coose a very similar solution as foxidrive here is another one:
#echo off &SETLOCAL enabledelayedexpansion
FOR %%a IN (*) DO (
SET search=%%a
IF "!search:~13!" neq "" SET /a $!search:~0,13!+=1 2>nul
)
FOR /f "tokens=1*delims=$=" %%a IN ('set "$"') DO if %%b equ 1 echo del "%%~a*"
The way i'd go about this is as follows, i will explain the logic and i'll leave you to do the coding.
You will parse all the file names into variables, while increasing each time.
Then you will set a limit to the number of loops to go through. Then you will search the first 13 characters of the file name and if the number of lines is equal to 1 then delete it. After you will increase the variable by 1 and go through the loop, at the end of each loop it will check if it has reached the limit aka the number of files in the directory, if it has reached the limit, end the loop, otherwise continue.
hah, i finally decided to do it after a guy decided to use my idea i described into actual code, anyway this is way shorter and a lot faster than his, tested+verified to work:
#echo off & setlocal enabledelayedexpansion
set dir=directoryyouwanttosearchin
for /f "delims=" %%a in ('dir /A:a /b %dir%') do set /A name+=1 & set file!name!=%%a
:LOOP
set /A cnt+=1
for /f "delims=" %%a in ('dir /A:a /b %dir% ^| find /C /I "!file%cnt%:~0,13!"') do set lines=%%a
if %lines%==1 del %dir%\!file%cnt%! > nul
if %cnt% NEQ %name% Goto :LOOP
exit /b
That's 9 lines :).

Resources