Check file name before deletion (windows Batch) - batch-file

Is there a way using Windows Batch to read a txt file list of file names. And if the name is present in the list to preserve that file but. If the file name is not found in the txt list that it is deleted.
I namely trying to filter out a horde of temporary files automatically generated by not cleaned out by AutoCAD.
The reason for reading a txt list would allow me to add or delete file names for processing.

Yes this is possible with Windows batch. Assuming you got a list of files FilesToKeep.txt with filenames like this:
WillBeKept.txt
WillAlsoBeKept.doc
in the same directory as the following batch script:
#echo OFF
pushd "%~dp0"
set "PathToCleanup=E:\Temp\Test"
for /F "tokens=*" %%F in ('dir /S/B/A-D %PathToCleanup%\*.*') do (
findstr /S %%~nxF FilesToKeep.txt >NUL || del /Q "%%F" )
This script loops through all files in PathToCleanup and if a filename is not present in FilesToCleanup.txt then the file will be deleted.

Related

Recursively append folder name to the files in Windows batch file

I would like to append my folder name to all the available .txt files inside a subfolder. Below is the file/directory structure. I need to achieve this in Windows BATCH script.
C:\Source\Source1\1\a.txt C:\Source\Source1\1\b.txt
C:\Source\Source1\2\a.txt C:\Source\Source1\2\b.txt
C:\Source\Source2\3\a.txt C:\Source\Source2\3\b.txt
The above files should be renamed like below:
C:\Source\Source1\1\1_a.txt C:\Source\Source1\1\1_b.txt
C:\Source\Source1\2\2_a.txt C:\Source\Source1\2\2_b.txt
C:\Source\Source2\3\3_a.txt C:\Source\Source2\3\3_b.txt
Similary, I have Source1...Source30 and under each source directory, I will have multiple folders with different numbers. I need to rename all the files under these directories and append the number(directory name) to the file name.
So far below is what I wrote:
for %%* in (.) do set CurrDirName=%%~nx*
echo %CurrDirName%
for /r %%x in (*.txt) do ren "%%x" "%CurrDirName%_%%x"
With this, I am able to achieve it in a single directory. I couldn't make it recursive. Could you guys please help me with this.
#echo OFF
SETLOCAL EnableExtensions
for /F "delims=" %%G in ('dir /B /S "C:\Source\*.txt"') do (
for %%g in ("%%~dpG.") do ECHO rename "%%~fG" "%%~nxg_%%~nxG"
)
pause
where the FOR loops are:
outer %%G loop creates a static list of .txt files (recursively), and
inner %%g loop gets the parent folder of every particular file.
The rename command is merely displayed using ECHO for debugging purposes. To make it operational, remove word ECHO (no sooner than debugged).
Moreover, I'd consider checking whether a particular file is already renamed…

How to check if zip or rar file contains 1 or more files?

For the purposes of saving space and organizing, I'm zipping bunch of files in my local and networked folders. They are mainly CAD files, like stp, igs, etc.
There are already existing zip files and some are extracted by other users, but the zip file still exists on the folders, which eats up space.
Is there a command line zip, rar, 7z. etc. to find out if an archive file contains only 1 file?
I'd like to figure this out as I'll extract the archives with single files in to the current directory whilst extracting archives with 1+ files to \archivename\ folder. Otherwise one folder with 30 STP files, will suddenly have 30 folders and 30 files extracted in them which I don't want.
I currently use a batch file with WinRAR to extract and another program to check for duplicates, then WinRAR batch to re-zip them based on file extension. (Reason: people use different archive methods and there are duplicates of files all over.)
Sample batch files:
for /F "delims=," %%f in ('dir *.stp /B' ) do (%path% a -afzip -r- -m5 -ed -ep -or -tl -y -df "%%f".zip "%%f")
for /F "delims=;" %%f in ('dir *.7z /B /S' ) do (%path% x -OR -ilogC:\Users\XXXX\Desktop\myLog.txt "%%f" "%%~dpf"\"%%~nf"\)
Once I can check for number of files in a zip, I'll add a recursive function.
I can use NTFS compression, but I also want to organize the folders, some folder have 1000 files in them, I surely want to reduce that to 1. These are mainly for archiving purposes.
Any help or thought would be appreciated.
I suggest the following commented batch file for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Extract all 7-Zip, RAR and ZIP archives in current directory into
rem subdirectories with name of archive file as name for subdirectory (-ad)
rem with running WinRAR for extraction in background (-ibck) which means
rem minimized to system tray with restoring also last access time (-tsa)
rem and creation time (-tsc) if existing in archive file and with skipping
rem files on extraction perhaps already present in the subdirectory with
rem same last modification time (-u), but overwriting automatically older
rem files in subdirectory if archive file contains an existing file with
rem a newer last modification time (-y) ignoring all errors (also -y).
for %%I in (7z rar zip) do "%ProgramFiles%\WinRAR\WinRAR.exe" x -ad -ibck -tsa -tsc -u -y *.%%I
rem If a subdirectory contains only 1 file, move that file to the current
rem directory with overwriting a perhaps already existing file with same
rem name in current directory and then remove the subdirectory.
for /D %%I in (*) do call :CheckSubDir "%%I"
rem Exit processing of the batch file without fall through to subroutine.
endlocal
goto :EOF
rem The subroutine CheckSubDir first checks for directories in directory
rem passed as parameter to the subroutine. A directory containing at
rem least one subdirectory is kept without any further processing.
rem If the directory does not contain a subdirectory, it searches for files
rem in the directory. If there are at least 2 files, the directory is kept
rem without any further processing.
rem But if the directory contains only 1 file, this file is moved to
rem current directory. Then the empty directory is deleted before exiting
rem the subroutine and continue batch file processing in calling loop.
rem Each directory containing no subdirectory and no file is removed, too.
:CheckSubDir
for /F "delims=" %%D in ('dir /AD /B "%~1\*" 2^>nul') do goto :EOF
setlocal EnableDelayedExpansion
set FileCount=0
for /F "delims=" %%F in ('dir /A-D /B "%~1\*" 2^>nul') do (
set /A FileCount+=1
if !FileCount! == 2 endlocal & goto :EOF
set "FileName=%%F"
)
if %FileCount% == 1 move /Y "%~1\%FileName%" "%FileName%"
rd "%~1"
endlocal
goto :EOF
Please read the comments for details what this batch file does on execution using WinRAR.
The batch file contains much more comment lines than real command lines.
2>nul in the last two FOR loops redirects the error message output by command DIR to handle STDERR in case of no directory or no file found to device NUL to suppress it. The redirection operator > must be escaped here with character caret ^ to be interpreted as redirection operator on execution of DIR command line and not already on parsing the FOR command line.
WinRAR supports many archive types on extraction. But WinRAR.exe is a GUI application and therefore does not support listing the contents of an archive file to console as Rar.exe supports.
The console version Rar.exe as well as free console application UnRAR.exe support both listing the archive file contents to handle STDOUT in various formats.
This difference on supported commands between WinRAR.exe and Rar.exe/UnRAR.exe can be seen by opening in WinRAR the help by clicking in menu Help on menu item Help topics, opening on help tab Contents the list item Command line mode, opening the list item Commands, clicking on list item Alphabetic commands list and comparing this list with the commands listed and described in text file Rar.txt in program files folder of WinRAR which is the manual for the console version.
Rar.txt lists and describes:
l[t[a],b] ... List archive contents [technical [all], bare]
v[t[a],b] ... Verbosely list archive contents [technical [all], bare].
Help of WinRAR does whether contain command l nor command v.
It would be of course also possible to run Rar.exe or UnRAR.exe on each *.rar file with command lb, count the number of lines output as done in above batch file to count the files and extract the *.rar archive file depending on the line count to current directory (1 line only) or to a subdirectory.
But it should be taken into account that on using bare list format and only 1 line output this line can be the name of an archived file or the name of an archived empty folder. The solution would be using standard list command and more analyze the attributes as well because a directory has attribute D while file does not have this attribute.
And for *.7z and *.zip files the same must be coded using 7z.exe or 7za.exe. The help of 7-Zip describes also the available commands and switches like the help of WinRAR.
But all those efforts do not make much sense in comparison to posted solution as the archive file has to be extracted at all and moving a file is done very fast as just the entry in file allocation table is modified and no data are copied or moved at all.
Running 7-Zip or Rar separately for first just listing each archive file contents, analyzing the list, and running 7-Zip or Rar once again on archive file for extraction is much slower than running WinRAR just 3 times (or less) to extract all archives and then move some files and remove some directories.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
dir /?
echo /?
endlocal /?
for /?
goto /?
move /?
rd /?
set /?
setlocal /?
See also the Microsoft TechNet article Using command redirection operators.
Taking the question literal the following batch uses 7z.exe (has to be reachable via the Path) list (l)-option to get the number of files included in the archive by filtering the last line.
#Echo off
Set Base=q:\Test
Pushd "%Base%"
For /f "delims=" %%A in (
'Dir /B/S/A-D *.zip *.7z *.rar'
) Do For /f "tokens=5" %%B in (
' 7z.exe l "%%~A" ^| findstr "files$" '
) Do If %%B equ 1 (
Echo Archive %%A contains 1 file
) else (
Echo Archive %%A contains %%B files
)
Popd
Sample Output:
Archive q:\Test\archiv.7z contains 135 files
Archive q:\Test\PoSh\powershellitunes\PowerScript-itunes.7z contains 1 file
Archive q:\Test\PoSh\_pdf_itextsharp\extract_pdf_pages_into_new_323689.zip contains 3 files
Archive q:\Test\_StackOverflow\Noodles\Filter0.8.zip contains 4 files
Archive q:\Test\2016\12\16\Path.rar contains 7 files
Archive q:\Test\_AllHelp.Win\allhelp.zip contains 7 files
Archive q:\Test\2017-02\pkzipc_40.rar contains 10 files

Batch Script Move file to directory based on its current directory

I'm attempting to sort a lot of files based on the current location of the file e.g.:
File 1 is located at C:\Work\Movies\Subs\Subtitle.txt
File 2 is located at C:\Work\Movies\Subs\Special\Subtitle.txt
File 3 is located at C:\Work\MoviesSpanish\Subs\Subtitle.txt
I'm trying to move the files like so:
File 1 to C:\Work\InProgress\Movies\Subs\Subtitle.txt
File 2 to C:\Work\InProgress\Movies\Subs\Special\Subtitle.txt
File 3 to C:\Work\InProgress\MoviesSpanish\Subs\Subtitle.txt
The Batch Script is to be located in C:\Work\MoveFile.bat
There are away more files then I listed above. Just for an estimate I would say around 300-500 per folder and there's a lot more subdirectories (e.g. .\Subs\01\ all the way up to .\Subs\300\ and they each contain a bunch of text files). I need to move all of the .txt files from their current locations to a new folder in C:\Work\ while retaining the rest of the directory location. So they get moved to C:\Work\[New Folder]\[Rest of Original Location]
I want to do this in batch but I'm not sure where to start. I already have the following code, which deletes files that don't contain a specific string:
for /r %%Z in (*.txt) do (
SET "count="
for /F "usebackq delims=," %%A in ("%%Z") do (
if /i "%%A"=="LN" set count=1
)
if not defined count echo del "%%Z"
if not defined count del "%%Z"
if defined count move "%%Z"
echo %count%
echo %%Z
)
But I'm not sure how to obtain the correct directory to move them into. I was thinking about for loop that reads the directory string of the file in question and uses delims=/ but it kept reading the text file rather then the path (and when I didn't use quotes on %%Z, it decided it couldn't find the file).
This is untested - it uses robocopy to move the *.txt files into a new location which is outside the source folder (because of cyclic copy restrictions) and then moves them back to the new "C:\Work\InProgress" folder.
If %temp% and c:\work are on the same drive then it should be swift.
Change c:\work in both places to a test folder with a few copies of your files and test it.
#echo off
robocopy "C:\Work" "%temp%\temporarymoviefolder" *.txt /s /mov
robocopy "%temp%\temporarymoviefolder" "C:\Work\InProgress" *.txt /s /mov
pause

How to write a Batch Script that searches for files based on list

Can anyone assist me in writing a batch script that searches for file names and outputs the location of the files to a text file. Example I have a file called list.txt located in a folder, C:\LocateFiles\list.txt. Located in the list.txt file are about 25 file names that I wish to determine if they are anywhere on the C:\ drive. If it locates any of the file names identified in the file list.txt it will output the path of all files found to a single file in C:\LocatedFiles\results.txt.
A million thanks,
Johnny Mac
#ECHO OFF
FOR /F %%F IN (C:\LocateFiles\List.txt) DO DIR /s/p/b %%F.* >> C:\LocateFiles\finds.txt
Save that as LocateFiles.cmd and place it in whichever directory you wish to search, note that C:\ is very large and will take quite a while! as in, forever, seriously, i really wouldnt, your call...
the file finds.txt will have the entire path for any file that matches up to the file names listed in List.txt
Also note, this finds files of any extension, but the filename itself must match exactly to whats in List.txt
The solution below search the files in the current directory just once, so it run faster.
#echo off
dir /S /B /A-D | findstr /I /G:C:\LocateFiles\list.txt > C:\LocatedFiles\results.txt
EDIT: New method added
The method below may run even faster. It is necessary to complete a timing test.
#echo off
setlocal EnableDelayedExpansion
rem Read file names from file list and assemble a long string with this format:
rem "filename1.ext*" "filename2.ext*" ...
set "fileList="
for /F "delims=" %%a in (C:\LocateFiles\list.txt) do set fileList=!fileList! "%%a*"
rem Search the files from current directory downwards
(for /R %%a in (%fileList%) do echo %%a) > C:\LocatedFiles\results.txt

List filenames and folder paths on csv using batch file

I have a batch file that lists the full file directories (including filename at the end) onto a csv file. I need it to produce this, but also just the filename in a separate column. I would like it so that the format is Filename in first column (including extension) and full file directory in second column. The batch file I currently have is:
dir C:\Users\Administrator\Desktop\test\Files\*.tif /b /s >>
C:\Users\Administrator\Desktop\test\Output.csv
EDIT: I forgot to mention the 'Files' folder contains many subfolders so I need it to process all files from all these subfolders.
Thanks in advance.
You just need to do this:
#echo off
setlocal
set "in=C:\Users\Administrator\Desktop\test\Files\*.tif"
set "out=C:\Users\Administrator\Desktop\test\Output.csv"
if not exist "%out%" type nul>"%out%"
for /f "delims=" %%a in ('dir /b/s %in%') do (
>>%out% echo "%%~nxa","%%a"
)
Iterate and write (help for for info on the %~ variable modifiers):
#echo off
cd C:\Users\Administrator\Desktop\test\Files
for %%f in (*.tif) do echo "%%~nxf","%%~dpf" >> Output.csv

Resources