I need a command to run from the Windows CLI to identify any folders (or sub folders) that contain only one file. If the folder contains two files, it should not be included. In the end, I need to output this list to a text file. It should contain the full folder path.
Ex: OutputLog.txt
C:\fold1
C:\fold1\sub
C:\fold3
C:\fold4
This should work to identify folders with one file.
#echo off
for /d /r "d:\base\folder" %%a in (*) do (
dir /b /a-d "%%a" 2>nul |find /c /v "" |findstr "^1$" >nul && >>file.txt echo %%a
)
#echo off
setlocal EnableDelayedExpansion
(for /D /R %%a in (*) do (
set count=0
for %%b in ("%%a\*.*") do set /A count+=1
if !count! equ 1 echo %%a
)) > OutputLog.txt
#echo off
set "parentfolder=c:\test"
for /f "tokens=* delims=" %%F in ('dir /s /a:d /b "%parentfolder%"') do (
dir "%%F"|findstr /b "1 File(s)" >nul 2>&1 && echo %%F
)
This will list all subfolders with only one file in a parent folder .As it checks the string of the dir command output it should be altered if language settings/windows version provide different DIR command output.
Related
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.
I would like to make a .bat file that will open the first file within a random folder/subfolders, in the same location as the .bat file.
The code I currently have only opens a random file.
#echo off
setlocal enableextensions disabledelayedexpansion
set "rootFolder=G:\Movies\Anime"
for /f "usebackq tokens=1,* delims=:" %%a in (`
cmd /q /v /e /c "for /f delims^= %%a in ('dir /a-d /s /b "%rootFolder%"') do echo(!random!:%%a"
^| sort 2^>nul
^| cmd /q /e /v /c "set /p ".^=" & echo(!.!"
`) do start "" "%%~b"
I also have a .bat file that generates a text file with a list of all folders in the same location. I'm not sure if it would be easier to reference that.
dir /b > Animelist.txt
Also if possible how to exclude it opening particular types of files such as jpegs / the other .bat file?
You can try with this
#echo off
setlocal enableextensions disabledelayedexpansion
set "rootFolder=%cd%"
set fileTypes= "*.avi" "*.mpeg" "*.mkv"
pushd "%rootFolder%" && (
for /f "usebackq tokens=1,* delims=:" %%a in (`
cmd /q /v /e /c "set p=&for /r %%a in (%fileTypes%) do if not !f!==%%~dpa (set f=%%~dpa&set /a ((%random% %% 16273^)+1^)*!random!&echo :%%~dpa)"
^| sort 2^>nul
^| cmd /q /e /v /c "set /p ".^=" && echo(!.!"
`) do pushd "%%~b." && (
for /f "delims=" %%c in ('
dir /b /a-d /on %fileTypes% 2^>nul
^| cmd /q /e /v /c "set /p ".^=" && echo(!.!"
') do start "" "%%~fc"
popd
)
popd
)
Decomposing the task in pieces
Configure where to search and what to search (first two set)
Change to the starting folder (pushd)
Execute a recursive search for the indicated file types and output the name of the folder where the file has been found (first cmd inside for /f
As more than one file can be found in the same folder, check that we will not output a duplicate element (if inside first cmd)
For each folder, generate a random number as a prefix (set /a) and output the folder (echo)
Sort the list on the random number (sort)
Get the first folder in the list. As the list is sorted on a random number, this folder has been random selected (second cmd inside for /f %%a)
Discard the random number and retrieve only the folder (the reason for the delims and tokens in the for /f %%a)
Change to the selected folder (pushd)
List the files of the indicated types inside the selected folder (dir)
From this list select only the first file (cmd)
Retrieve the selected file (for /f %%c)
Start the selected file (start)
Return to previous folder (popd)
Return to the starting folder (popd)
The random selection of a folder is unambiguous.
The first video file is a bit more difficult. If using dir with several extensions like #aschipfl suggested, this predetermines which extensions are looked for and found first.
The other way with excluding file types is more tedious without knowing which types might occur.
Here my batch Edited Streamlined some parts:
#echo off
setlocal enableextensions Enabledelayedexpansion
Set Cnt=0
Set "Exclude=.bat$ .cmd$ .jpg$ .jpeg$ .txt$"
Pushd "G:\Movies\Anime"
(Echo::: Numbered List of folders
For /f "delims=" %%F in (
'Dir /B/S/AD/ON'
) Do Set /A Cnt+=1&Echo:!Cnt!:%%F
)>DirList.txt
:: Get Random num 1..Cnt
Set /A RndDir=%Random% %% Cnt+1
:: Get random folder name
For /f "tokens=1,* Delims=:" %%F in (
'Findstr "^%RndDir%:" DirList.txt '
) Do Set "DirName=%%G"
Echo selected %RndDir% of %Cnt% = folder %DirName%
Pushd "%DirName%
Set "FileName"
For /f "Delims=" %%F in (
'Dir /B/A-D ^|findstr /i /V "%Exclude%"'
) Do If Not defined FileName Set "FileName=%%~F"
If defined FileName Start "" "%FileName%"
Popd
Popd
Goto :Eof
I need to find all * .avi files (even in subfolders). But I want to exclude files with specific part of the name (* demux.avi). Something like this:
FOR /R %%g IN (*.avi) DO (
if "%%g"=="*demux.avi" ( - THIS PART IS WRONG
echo "%%g" excluded
) else (
echo "%%g"
)
)
I expect results:
file1.avi
file1 demux.avi excluded
file2.avi
**
Try this:
FOR /F %%g IN ('dir /b /s "*.avi"^|find /i /v "demux"') DO ( whatever )
We are basically saying look for all avi files in this folder and subfolders and pipe them to find.
Use finds /V switch that finds all lines NOT containing "demux" and run your command on them.
Like this :
#echo off&cls
for /f "delims=" %%a in ('dir /b/a-d *.avi') do (echo %%a | find "demux" && echo %%a [Excluded] || echo %%a [OK])
In place of echo %%a [Excluded] or echo %%a [OK] you can do what you want (DEL, REN,MOVE,...)
Edit :
To just have the name of the file when your using /S option of DIR
#echo off&cls
for /f "delims=" %%a in ('dir /s/b/a-d *.avi') do (echo %%~na | find "demux" && echo %%~na [Excluded] || echo %%~na [OK])
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
The batch file below recursively echos files and folders while adding some simple formatting, such as indenting to show the recursion depth, adding "/ " before folder names, "*" before certain files, and skipping folders named "Archive". It works great except that files and folders are sorted randomly, rather than alphabetically. How could this be changed to sort both files and folders alphabetically?
#echo off
setlocal disableDelayedExpansion
pushd %1
set "tab= "
set "indent="
call :run
exit /b
:run
REM echo the root folder name
for %%F in (.) do echo %%~fF
echo ------------------------------------------------------------------
set "folderBullet=\"
set "fileBullet=*"
:listFolder
setlocal
REM echo the files in the folder
for %%F in (*.txt *.pdf *.doc* *.xls*) do echo %indent%%fileBullet% %%F - %%~tF
REM loop through the folders
for /d %%F in (*) do (
REM skip "Archive" folder
if /i not "%%F"=="Archive" (
REM if in "Issued" folder change the file bullet
if /i "%%F"=="Issued" set "fileBullet= "
echo %indent%%folderBullet% %%F
pushd "%%F"
set "indent=%indent%%tab%"
call :listFolder
REM if leaving "Issued folder change fileBullet
if /i "%%F"=="Issued" set "fileBullet=*"
popd
))
exit /b
Very little change required. Convert FOR loops to FOR /F running sorted DIR commands. The /A-D option lists files only, and /AD lists directories only.
This version sorts files by name
#echo off
setlocal disableDelayedExpansion
pushd %1
set "tab= "
set "indent="
call :run
exit /b
:run
REM echo the root folder name
for %%F in (.) do echo %%~fF
echo ------------------------------------------------------------------
set "folderBullet=\"
set "fileBullet=*"
:listFolder
setlocal
REM echo the files in the folder
for /f "eol=: delims=" %%F in (
'dir /b /a-d /one *.txt *.pdf *.doc* *.xls* 2^>nul'
) do echo %indent%%fileBullet% %%F - %%~tF
REM loop through the folders
for /f "eol=: delims=" %%F in ('dir /b /ad /one 2^>nul') do (
REM skip "Archive" folder
if /i not "%%F"=="Archive" (
REM if in "Issued" folder change the file bullet
if /i "%%F"=="Issued" set "fileBullet= "
echo %indent%%folderBullet% %%F
pushd "%%F"
set "indent=%indent%%tab%"
call :listFolder
REM if leaving "Issued folder change fileBullet
if /i "%%F"=="Issued" set "fileBullet=*"
popd
))
exit /b
To sort by extension first, then by name, simply change /ONE to /OEN.
Try changing your for /d loop from
for /d %%F in (*) do
to
for /f "delims=" %%F in ('dir /b /o:n *.') do
and see whether that makes a difference. Actually, ordering by name is the default behavior for dir, so you could probably get away with
for /f "delims=" %%F in ('dir /b *.') do
If some of your directory names have dots in them, you'll need to change it a little.
for /f "delims=" %%F in ('dir /b') do (
rem Is this a directory?
if exist "%%F\" (
rem do your worst....
)
)