I want to traverse all files within a specific directory and all its subdirectories and then print out the folder name of each file.
I don't know how to get the folder name of each file.
FOR /F "delims=" %%x IN ('dir /B /A /S *') DO (
:: Suppose %%x is 'C:\myfolder\a.txt', the desired output is 'myfolder'
:: %%~nx is not correct
echo ???
)
If you want just the path (without drive, without filename), %%~px is what you need
If you want just the last folder, not the complete path. This is indeed not that trivial:
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%x in ('dir /b /a /s *') do (
set "line=%%~dpx"
for /f "delims=" %%y in ("!line:\=.!") do set folder=%%~xy
echo %%~nxx is in: !folder:~1!
)
I think this is what you're looking for:
#echo off
FOR /F "delims=" %%F IN ('dir /B /A /S *') DO (
for %%D in ("%%~dpF\.") do echo %%~nxD
)
pause
Related
Can anyone please explain to me how batch scripts work in Windows? I have a folder that contains subfolders, and those contain images. I need a script that automatically deletes images from 7 and up in these subfolders, just to leave a maximum of 6 images in each subfolder, ideally the first 6 alphabetically. I found a few scripts, saved them as .bat, but I have no idea what to do next.
1
#echo off
setlocal
set /a cnt=0
set "keep=6"
for /f "eol=: delims=" %%F in ('dir /b /o-d /a-d *.jpeg') do (
if defined keep (
2>nul set /a "cnt+=1, 1/(keep-cnt)" || set "keep="
) else del "%%F"
)
2
#echo off
for /f "tokens=1* delims=:" %%a in ('dir /b /o-d *.jpeg ^| findstr /N "^"') do (
if %%a gtr 6 del "%%b"
)
3
for /f "skip=7 eol=: delims=" %%F in ('dir /b /o-d /a-d *.jpeg') do #del "%%F"
4
#echo off
setlocal enableextensions disabledelayedexpansion
rem How many elements to keep
set "keep=6"
rem Retrieve folder from batch arguments
set "folder=%~1"
rem If no folder indicated, use current active directory
if not defined folder for %%a in (.) do set "folder=%%~fa"
rem Ensure we are working in the correct folder
pushd "%folder%" && (
rem For each element in the folder, skipping the first n
for /f "skip=%keep% delims=" %%a in (' dir /b /on ') do (
rem If it is a folder, use rmdir, else use del
if exist "%%a\" ( echo rmdir /s /q "%%a" ) else ( echo del "%%a" )
)
rem Work done. Return to previous active directory
popd
) || (
rem Folder change failed
echo Target folder does no exist
)
I finally found a script that works the way I need it to
for /f %%a in ('dir /b /ad') do (
for /f "skip=6" %%b in ('dir /b %%a /on') do (
del %%a\%%b
)
)
I'm trying to clean the temp files, but I want skip some files that cointain a certain name. No matter the extension it is.
Tried this way:
#echo off
setlocal EnableDelayedExpansion
for /f "eol=: delims=" %F in ('dir "%windir%/temp" /b /a-d * ') do find "TESTE" %F > nul || del "%F"
pause
Wanted all files that cointains TESTE in name got skipped from deletation.
But my script not even run.
Can someone explain me what is wrong?
It is not absolutely clear whether you want to exclude files from deletion whose names or whose contents include a certain string; anyway, this is for the former:
pushd "%WinDir%\TEMP" && (
for /F "delims= eol=|" %%F in ('
dir /B /A:-D "*.*" ^| findstr /V /I /C:"TESTE"
') do (
ECHO del /F "%%F"
)
popd
)
Once you are satisfied with the output, remove the upper-case ECHO command.
The above script would also not delete files whose extensions contain the given string. But if you want to regard only the base name, you might want to use this code instead:
pushd "%WinDir%\TEMP" && (
for /F "delims= eol=|" %%F in ('
dir /B /A:-D "*.*"
') do (
set "NAME=%%~nF"
setlocal EnableDelayedExpansion
if /I "!NAME:TESTE=!"=="!NAME!" (
endlocal
ECHO del /F "%%F"
) else endlocal
)
popd
)
You should be able to use findstr.exe with its /V and /M options to list your unwanted files.
#SetLocal EnableExtensions
#For /F "Delims=" %%G In (
'%__AppDir__%findstr.exe /VPMLI "TESTE" "%SystemRoot%\TEMP\*" 2^>NUL'
)Do #Del /A/F "%%G"
#Pause
Please note that the \Windows\Temp directory is usually protected, so you may need to run this script 'as administrator'.
In my hard disk I have the following structure:
ROOTFOLDER
├───FOLDER1
│ └───TMPFOLDER
│ ├───FOLDERTODELETE1
│ ├───FOLDERTODELETE2
│ └───FOLDERTODELETE3
├───FOLDER2
│ └───TMPFOLDER
│ ├───FOLDERTODELETE4
│ └───FOLDERTODELETE5
└───FOLDER3
└───TMPFOLDER
├───FOLDERTODELETE6
├───FOLDERTODELETE7
└───FOLDERTODELETE8
I need to create a kind of script (I was thinking about a batch file, but any other solution will be appreciated) to delete all folders within each folders with a specific name (in this case TMPFOLDER) and created before today.
Following to your needs the batch script below will do what you need. Remove the echo in front of the rmdir command if it's okay for you. Take care that the script uses the current working directory. Remove /q if you want to be asked for each directory that should be deleted:
#echo off
set "tmpfolder=TMPFOLDER"
for /f "tokens=*" %%D in ('dir /b /a:d "*"') do (
for /f "tokens=*" %%E in ('dir /b /a:d "%%D\*" ^| findstr /l /x %tmpfolder%') do (
echo Found temp folder: "%%D\%%E"
for /f "tokens=*" %%F in ('dir /b /a:d "%%D\%%E\*"') do (
echo rmdir /s /q "%%D\%%E\%%F"
)
)
)
Edit #1:
The above script does not take care of the creation date of the folder that should be removed. You want only folders to be deleted which have a creation date before today. The following script takes care of that. Look here how to get dates of folder and here how to compare dates:
#echo off
setlocal EnableDelayedExpansion
set "tmpfolder=TMPFOLDER"
for /f "tokens=*" %%D in ('dir /b /a:d "*"') do (
for /f "tokens=*" %%E in ('dir /b /a:d "%%D\*" ^| findstr /x /c:"%tmpfolder%"') do (
rem echo Found temp folder: "%%D\%%E"
for /f "tokens=*" %%F in ('dir /b /a:d "%%D\%%E\*"') do (
rem echo Subfolder: "%%F"
set "curdate=!date!"
set "dirdate="
echo GETDATE
call :getdate dirdate "%%D\%%E\%%F"
set "dirdate=!dirdate:~-4!!dirdate:~3,2!!dirdate:~0,2!"
set "curdate=!curdate:~-4!!curdate:~3,2!!curdate:~0,2!"
rem echo dirdate: "!dirdate!"
rem echo curdate: "!curdate!"
rem echo.
if [!dirdate!] LSS [!curdate!] (
echo rmdir /s /q "%%D\%%E\%%F"
)
)
)
)
goto :EOF
:getdate
rem call: getdate date(dstParam) folder(srcParam)
for /f "skip=5 tokens=1 delims= " %%A in ('dir /a:d /o:d /t:c "%~2"') do (
set "%~1=%%A"
goto :EOF
)
Command reference links from ss64.com:
DelayedExpansion
set
for /f
dir
findstr
if
call
goto
rem
Although an answer has already been accepted, I have decided to post this untested idea as an alternative:
#Echo Off
SetLocal EnableDelayedExpansion
For /F "Delims=" %%A In ('WMIC OS Get LocalDateTime') Do For %%B In (%%~nA
) Do Set "TD=%%B" & Set "TD=!TD:~,8!"
For /D /R "ROOTFOLDER" %%A In ("TMPFOLD?R") Do If /I "%%~nxA"=="TMPFOLDER" (
Set "FP=%%~pA" & Set "FP=!FP:\=\\!"
WMIC FSDir Where "Path='!FP!' And FileName='TMPFOLDER'" Get CreationDate^
|FindStr/B "%TD%">Nul||Echo=RD/S/Q "%%A")
Timeout -1
You may need to change ROOTFOLDER and all instances of TMPFOLDER as necessary, remembering to use a ? to replace one of the characters in the first instance of TMPFOLDER.
If the output appears to be correct, remove the last line and Echo= from the line above it.
I would like to make a script with Batch. I want from this script to check it out, If a folder contains a file, "list.txt", and if it is in the folder i want to make a copy in an other location. I wrote some lines of code but it's not working. Any ideas?
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:loop
for /f %%i in ('dir "C:\Users\ntosis\Desktop\Draft" /ad /o:d /s /b') do (
SET a=%%i
for /R %%a %%t in (*.txt) do if "%%~nxt"=="list.txt" SET p=%%~dpnxt
echo !p!
IF DEFINED %p% ( robocopy C:\Users\ntosis\Desktop\Draft\%a% C:\Users\ntosis\Desktop\Copied\%a% /MOVE /E )
)
echo Folder is empty or does not exist
timeout /t 15
goto loop
The problem in this moment is that the second loop does not the check right.
How about this:
for /f %%i in ('dir "C:\Users\ntosis\Desktop\Draft" /ad /o:d /s /b') do (
IF EXIST "%%i\list.txt" (
robocopy %%i C:\Users\ntosis\Desktop\Copied\ /MOVE /E
)
)
#echo off
setlocal enableextensions disabledelayedexpansion
set "source=C:\Users\ntosis\Desktop\Draft"
set "target=C:\Users\ntosis\Desktop\Copied"
for /l %%t in (0) do (
set "found="
for /d /r "%source%" %%a in (list.txt) do if exist "%%a" (
for %%b in ("%%~dpa.") do (
echo Found "%%a"
robocopy "%%~dpa." "%target%\%%~nxb" /move /e
)
set "found=1"
)
if not defined found (
echo folder is empty or does not exist
)
timeout /t 15
)
Hi I'm trying to make a batch file that digs thru a directory and checks if all the files in its sub-directories are the same as in another directory (with the same name and same sub-directory names)
ex:
C:/Users/Administrator/desktop/directory1/global/config/project.config
C:/directory2/global/config/project.config
I'm able to fetch all the files that need to be compared with a for loop
The echo %%f gives me a path like:
C:/Users/Administrator/directory1/global/config/project.config
But I want to remove the beginning and store it in a new variable so I can easily compare files with an FC command. I don't know how to correctly do a string substitution when in a for loop. I want to get just this:
/global/config/project.config
my code for now
set b="c:\Users\Administrator\desktop\"
set j=""
for /f %%f in ('dir /a:-d /s /b /r c:\Users\Administrator\desktop\global') do (
set c=%%f
%c:b=j%
echo %%c
)
#echo off
set "dir1=c:\smth"
set "dir2=c:\dir\smth2"
setlocal enableDelyaedExpansion
for /f %%F in ('dir /a:-d /s /b /r "%dir1%"') do (
set "file_path=%%F"
if not exist "!file_path:%dir1%=%dir2%!" (
echo file %%F does not exists in %dir2%
)
)
endlocal
The better way to use a call function
setlocal enableDelyaedExpansion
for /f %%F in ('dir /a:-d /s /b /r "%dir1%"') do call :foo %%F
:foo
set "file_path=%1"
if not exist "!file_path:%dir1%=%dir2%!" (
echo file %1 does not exists in %dir2%
)