I have following script that removes all subdirectory from ROOT directory and removes all files in a ROOT directory except *.bat files.
pause
FOR /R C:\Temp\ %%F IN (*.*) DO IF NOT "%%~xF" == ".bat" DEL /F /S "%%F"
for /d %%i in ("c:\Temp\*") do rmdir /s /q "%%i"
pause
Help me improve script that it can also scan files *.bat in a ROOT subdirectories and remove all files with other extensions.
Test. If what it shows in console is what needs to be done, remove the echo command from destructive lines keeping the rmdir or del commands.
#echo off
setlocal enableextensions
set "root=c:\temp"
rem For the %root% tree
for /r "%root%" %%d in (.) do (
rem Test for the presence of .bat files under directory
dir /s /b "%%~fd\*.bat" 2>nul | find /v "" > nul
if errorlevel 1 (
rem If there is no .bat files under directory, remove directory
echo(**** rmdir /s /q "%%~fd"
) else (
rem There are bat files in directory or under it. Remove anything else in this directory
for %%f in ("%%~fd\*") do if not "%%~xf"==".bat" echo(-------- del "%%~ff"
)
)
EDITED - To adapt to comments - How to adapt the code so it will process more than one root folder? Take the code and convert it into a subroutine, then call it with the corresponding root. Iterate over the list of root directories
#echo off
setlocal enableextensions
for %%r in ("c:\temp" "c:\temp2" "c:\temp3") do call :processRoot %%r
endlocal
exit /b
:processRoot
setlocal enableextensions disabledelayedexpansion
set "root=%~1"
rem For the %root% tree
for /r "%root%" %%d in (.) do (
rem Test for the presence of .bat files under directory
dir /a /s /b "%%~fd\*.bat" 2>nul | find /v "" > nul
if errorlevel 1 (
rem If there is no .bat files under directory, remove directory
echo(**** rmdir /s /q "%%~fd"
) else (
rem There are bat files in directory or under it. Remove anything else in this directory
for %%f in ("%%~fd\*") do if not "%%~xf"==".bat" echo(-------- del "%%~ff"
)
)
endlocal
goto :eof
Related
I am trying to write a batch script that recursively lists all directories and their files with *.js type in the below format:
For example, if I start with the C:\project directory
c:\project
project.js
project_time.js
c:\project\core
core.js
core_render.js
core_application.js
I tried to implement the above logic in code as follows:
#echo off
for /r %%f in (*.js) do (
echo %%f >> names.txt
)
pause
I was not able to print the directory under which the files are listed.
#echo off
setlocal disabledelayedexpansion
set "lastdir="
( for /r %%A in (*.js) do (
set "nextdir=%%~dpA"
setlocal enabledelayedexpansion
if /i not "!lastdir!" == "!nextdir!" (
rem Empty line and directory path.
if defined lastdir #echo(
#echo !nextdir!
)
endlocal
rem Filename.
#echo %%~nxA
set "lastdir=%%~dpA"
)
) > "names.txt"
The lastdir variable is to record the last directory path so it is echoed only once.
If lastdir is different to %%~dpA:
If lastdir is defined, then an empty line will be echoed.
Directory path of found file is echoed.
Filename is always echoed.
for modifiers dp is the drive and path. nx is the name and extension.
setlocal enabledelayedexpansion is used only where needed so paths with ! are not vulnerable.
I am not going to suggest a command line solution as it would be very long. Instead suggest use of tree command if the output format is suitable.
Here's an untested example, (I'm not expecting it to be quick if your base directory is large):
#Echo Off
(
For /F "Delims=" %%G In ('Dir /B /S /A:D "C:\Project" 2^> NUL') Do (
%__AppDir__%where.exe /Q "%%G":*.js 1> NUL 2> NUL
If Not ErrorLevel 1 (
Echo/
Echo %%G
For /F "EOL=| Delims=" %%H In ('%__AppDir__%where.exe "%%G":*.js')Do (
Echo %%~nxH
)
)
)
) 1> "names.txt"
Pause
If you prefer to run something from the Command Prompt, then try this version:
(For /F "Delims=" %G In ('Dir /B/S/AD "C:\Project" 2^>NUL')Do #(%__AppDir__%where.exe /Q "%G":*.js >NUL 2>&1&&(Echo/&Echo %G&For /F "EOL=|Delims=" %H In ('%__AppDir__%where.exe "%G":*.js')Do #Echo %~nxH)))>"names.txt"
Two simple ways to do this:
dir /S *.js
You get the answers, just as you requested.
FORFILES /S /M *.js /C "cmd /c echo #path"
You get complete path for every file.
Idea was to merge all jpg files in separate folders in the directory of the batch files to a new folder without any subdirectories. It worked as expected for a few hours but now it keeps looping copying the same files of the first folder again and again. Any clue on what is really wrong?
#echo off
::rmdir /S .\merge
::pause
mkdir .\merge
call :treeProcess
goto :eof
::pause
:treeProcess
rem Do whatever you want here over the files of this subdir, for example:
for %%f in (*.jpg) do (
echo %%f
xcopy .\*.jpg ..\merge\ /Y
)
for /D %%d in (*) do (
cd %%d
call :treeProcess
cd ..
)
exit /b
I got a solution but still confused as if I remove echo %%G, echo %%H, echo back to .. the code still fails saying ( unexpected at this time.
#echo off
::SETLOCAL EnableDelayedExpansion
::rmdir /S .\merge
::pause
::mkdir .\merge
dir /b /a-d
cd .
call :treeProcess
goto :eof
pause
:treeProcess
REM rem Do whatever you want here over the files of this subdir, for example:
for %%G in (*.jpg) do (
echo %%G
echo %%H
::echo inside %%H
REM rem xcopy .\*.jpg ..\merge\ /e /Y
xcopy .\%%G ..\merge\ /Y
)
FOR /D %%H in (*20*) do (
cd %%H
rem dir /b /a-d
call :treeProcess
cd ..
echo back to ..
)
REM exit /b
REM :treeProcess
rem Do whatever you want here over the files of this subdir, for example:
REM %%G is a good choice because it does not conflict with any of the pathname format letters (a, d, f, n, p, s, t, x) and provides the longest run of non-conflicting letters for use as implicit parameters.
REM G > H > I > J > K > L > M
REM Format letters are case sensitive, so using a capital letter is also a good way to avoid conflicts %%A rather than %%a.
exit /b
I have source folder: c:\prefix\bin
I want to copy a set of specified files from source folder and its subfolders.
Lets say I want to copy:
bin
... gtsam.dll
... msvcr120.dll
... intel64\
... vc12\
... tbb.dll
To be more clearly for what I want to copy:
.\gtsam.dll .\msvcr120.dll .\intel64\vc12\tbb.dll
There are many files in the source directory and many subdirectories that I don't want to copy. And all the specified files I have to copy do not share a wild card. They are not all *.dll to copy to c:\dst
How I can do it with the most elegant way?
Using copy, or xcopy, or robocopy?
I suggest to create first a simple text file containing line by line the files to copy with relative path.
Example for FilesList.txt:
gtsam.dll
msvcr120.dll
intel64\vc12\tbb.dll
It is up to you in which directory to store this list file with the names of the files to copy.
The code below expects this file in directory C:\prefix\bin.
Then create a batch file with following code:
#echo off
pushd "C:\prefix\bin"
for /F "usebackq delims=" %%F in ("FilesList.txt") do (
%SystemRoot%\System32\xcopy.exe "%%~F" C:\dst\ /C /H /I /K /Q /R /Y >nul
)
popd
If target is specified with a backslash at end as done here and option /I is used, console application xcopy expects that C:\dst is a directory and even creates the entire directory structure to this directory automatically if not already existing.
Or you use this script with command copy and making sure the destination directory exists before copying the files.
#echo off
if not exist "C:\dst" (
md "C:\dst"
if errorlevel 1 (
echo.
echo Failed to create directory C:\dst
echo.
pause
goto :EOF
)
)
pushd "C:\prefix\bin"
for /F "usebackq delims=" %%F in ("FilesList.txt") do (
copy /B /Y "%%~F" C:\dst\ >nul
)
popd
Command md creates also entire directory tree on creating a directory with command extensions enabled as by default.
In both cases the directory C:\dst contains after batch file execution:
gtsam.dll
msvcr120.dll
tbb.dll
The main advantage of using a list file containing the names of the files to copy with relative path is easy updating in future without the need to change the batch code.
But let's say the files should be copied with duplicating the directory structure from source to destination directory resulting in directory C:\dst containing after batch file execution:
gtsam.dll
msvcr120.dll
intel64
vc12
tbb.dll
In this case the batch code with xcopy could be:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
pushd "C:\prefix\bin"
if "%CD:~-1%" == "\" ( set "BasePath=%CD%" ) else ( set "BasePath=%CD%\" )
for /F "usebackq delims=" %%F in ("FilesList.txt") do (
set "SourcePath=%%~dpF"
set "RelativePath=!SourcePath:%BasePath%=!"
%SystemRoot%\System32\xcopy.exe "%%~F" "C:\dst\!RelativePath!" /C /H /I /K /Q /R /Y >nul
)
popd
endlocal
And the batch code using copy could be:
#echo off
if not exist "C:\dst" (
md "C:\dst"
if errorlevel 1 (
echo.
echo Failed to create directory C:\dst
echo.
pause
goto :EOF
)
)
setlocal EnableDelayedExpansion
pushd "C:\prefix\bin"
if "%CD:~-1%" == "\" ( set "BasePath=%CD%" ) else ( set "BasePath=%CD%\" )
for /F "usebackq delims=" %%F in ("FilesList.txt") do (
set "SourcePath=%%~dpF"
set "RelativePath=!SourcePath:%BasePath%=!"
md "C:\dst\!RelativePath!" 2>nul
copy /B /Y "%%~F" "C:\dst\!RelativePath!" >nul
)
popd
endlocal
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.
copy /?
echo /?
endlocal /?
if /?
for /?
goto /?
md /?
pause /?
popd /?
pushd /?
set /?
setlocal /?
xcopy /?
Not tested:
#echo off
set "basedir=c:\prefix\bin"
set "destination=c:\destination"
for /r "%basedir%" %%# in (*gtsam.dll *msvcr120.dll *tbb.dll) do (
copy "%%~f#" "%destination%"
)
After successfully removing a bunch of Google Drive Folder duplicates, some files retain a "filename(2)"name.
Is there a way to batch rename every file so the parenthesis and the number inside the parenthesis is gone?
That includes folders and sub-folders.
Try like this :
Create a file test.bat with the code below in it and replace the path to test in the var $path
#echo off
set $path="C:\Users\CN Micros\Desktop\PROGRAMMATION\test"
for /f "tokens=1-3 delims=^(^)" %%a in ('dir /b/a-d %$path%') do (
if exist %$path%\"%%a(%%b)%%c" echo ren %$path%\"%%a(%%b)%%c" "%%a%%c"
)
pause
Then run it in the CMD or by double clicking.
If the output is ok for you remove the echo
The program create 3 tokens : %%a = what's before the (), %%b What's inside the () and %%c what's after the ().
Then we arrange this 3 tokens to rename the files without the ().
If you have some file who have the same final name ie : "file(1)name", "file(2)name" --> "filename"
It will work only with the first one. If you have this case you have to add a counter at the end of file to be sure that they will be renamed.
This will create renfiles.bat.txt for you to examine in Notepad and then rename to .bat and execute if you are happy with it.
#echo off
dir /b /a-d *(*).* |find /i /v "%~nx0" |find /i /v "repl.bat" |repl "(.*)\(.*\)(\..*)" "ren \q$&\q \q$1$2\q" xa >"renfiles.bat.txt"
This uses a helper batch file called repl.bat - download from: https://www.dropbox.com/s/qidqwztmetbvklt/repl.bat
Place repl.bat in the same folder as the batch file or in a folder that is on the path.
Edit: This version will recurse through subdirectories:
#echo off
dir /b /s /a-d *(*).* |find /i /v "%~nx0" |find /i /v "repl.bat" |repl ".*\\(.*)\(.*\)(\..*)" "ren \q$&\q \q$1$2\q" xa >"renfiles.bat.txt"
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%a IN (
'dir /b /s /a-d "%sourcedir%\*" '
) DO (
SET "name=%%~na"
SETLOCAL ENABLEDELAYEDEXPANSION
SET "newname=!name:)=!"
SET "newname=!newname:(=!"
IF "!name!" neq "!newname!" (
IF EXIST "%%~dpa!newname!%%~xa" (ECHO cannot RENAME %%a
) ELSE (ECHO(REN "%%a" "!newname!%%~xa")
)
endlocal
)
GOTO :EOF
You'd need to set your required directory into sourcedir. I used u:\sourcedir which suits my testing.
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(REN to REN to actually rename the files.
I have many files with the following structure:
1969/ar/1.jpg
1969/ar/2.jpg
1969/he/1.jpg
1969/he/2.jpg
1969/en/1.jpg
1969/en/2.jpg
1970/ar/1.jpg
etc...
I want to rename all of them, with one command, to one directory, while their names reflect their original folder location.
1969_ar_1.jpg
1969_ar_2.jpg
1969_he_1.jpg
1969_he_2.jpg
1969_en_1.jpg
1969_en_2.jpg
1970_ar_1.jpg
etc...
Is it possible to do so with one command or a batch file?
Thanks!
You may do that to move the files to the base folder with this command-line:
for /R %a in (*) do #set f=%a& set f=!f:%cd%\=!& move "%a" !f:\=_!
Execute it from the folder that contain the 1969, 1970... folders. IMPORTANT!: Delayed Expansion must be active in order for this line to work, so you must previously activate it executing cmd.exe with /V switch this way: cmd /V.
For example:
>xcopy test backup /s
test\1969\ar\1.jpg
test\1969\ar\2.jpg
test\1969\en\1.jpg
test\1969\en\2.jpg
test\1969\he\1.jpg
test\1969\he\2.jpg
test\1970\ar\1.jpg
7 File(s) copied
>cd test
>dir /B
1969
1970
>for /R %a in (*) do #set f=%a& set f=!f:%cd%\=!& move "%a" !f:\=_!
>dir /B
1969
1969_ar_1.jpg
1969_ar_2.jpg
1969_en_1.jpg
1969_en_2.jpg
1969_he_1.jpg
1969_he_2.jpg
1970
1970_ar_1.jpg
Modify the line this way to move the files to another folder:
for /R %a in (*) do #set f=%a& set f=!f:%cd%\=!& move "%a" "\other\folder\!f:\=_!"
Or via this Batch file:
#echo off
setlocal EnableDelayedExpansion
for /R %%a in (*) do set f=%%a& set f=!f:%cd%\=!& move "%%a" "\other\folder\!f:\=_!"
Run this from the base of the tree that contains all *.jpg files.
Change the target folder to where you want the files to go:
Test it on some samples first.
#echo off
for /f "delims=" %%z in ('dir "*.jpg" /b /s /a-d ') do (
for %%a in ("%%~dpz%\.") do (
for %%b in ("%%~dpa\.") do (
ren "%%z" "%%~nxb_%%~nxa_%%~nxz"
move "%%~dpz\%%~nxb_%%~nxa_%%~nxz" "c:\target\folder"
)
)
)
pause
try this (look at the output and remove the word echo before move, if it is OK):
#echo off &setlocal
for /d %%i in (19* 20*) do (
cmd /c "for /r "%%i" %%j in (*.jpg) do #for %%k in ("%%~dpj.") do #echo move "%%~j" "%%i_%%~nk_%%~nxj""
)