Windows batch file: converting all files in subfolders - windows

I need to write a batch file to convert every file in every subfolder. I came up to the following solution:
set INDIR=<some path>
set OUTDIR=<some path>
mkdir "%OUTDIR%"
for /f "tokens=1*delims=." %%f in ('dir %INDIR% /b /a-d') do (
rem %%f is file name
rem %%g is extension
call convert_one . %%f %%g
)
)
for /f "delims==" %%d in ('dir %INDIR% /ad /b') do (
rem %%d is relative path
mkdir %OUTDIR%\%%d
for /f "tokens=1*delims=." %%f in ('dir %INDIR%\%%d /b /a-d') do (
rem %%f is file name
rem %%g is extension
call convert_one %%d %%f %%g
)
)
The problem is that it iterates through the first level subfolders only. When I add /s key to the dir command it returns full pathes instead of relative.
How can I improve the script to process all levels subfolders?
PS: I need separate values for relative path, file name and extension.

You don't show us convert_one - but here's a few clues...
for /f "delims=" %%f in ('dir %INDIR% /b /s /a-d') do (
rem %%~dpnf is file name and path
rem %%~dpf is file absolute path
rem %%~nf is file name-part
rem %%~xf is extension
call convert_one "%%~dpf" "%%nf" %%~xf
)
)
See for /?|more from the prompt for more...
(within your subroutine, %~n for n=1..9 strips quotes if needed - applying quotes means that "strings containing spaces" are regarded as a single string.
- maybe make your destination directory there...?)

#echo off
setlocal enableextensions disabledelayedexpansion
set "INDIR=%cd%"
set "OUTDIR=..\out"
subst :: /d >nul 2>&1 & subst :: "%INDIR%"
for /r "::\." %%a in (*) do (
if not exist "%OUTDIR%%%~pa" md "%OUTDIR%%%~pa"
call convert_one ".%%~pa" "%%~na" "%%~xa"
)
subst :: /d
This operates creating a subst drive, so the root of the drive point to the in folder. Then iterates over the folder structure recreating the structure in the output folder and calling the subroutine with the indicated parameters

Related

Write a script to recursively list directories and files within it in Batch script

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.

Batch file to search directory for list of files and copy to single folder

I have a .txt file with a list of files that are on a network drive (M:). I need a batch file to go through that list, search for the files which are in sub-directories of a single folder on that drive, and then copy them to another folder. I have tried quite a few solutions with no luck.
the text file is a list of files and extensions i.e.
abc.step
afer.iges
ca76dc7d.sldprt
Here's what I tried so far
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
cls
set dest=C:\Users\kduquette.000\Desktop\Files
for /f "TOKENS=*" %%f in (C:Desktop\Files\list.txt) do (
set i=1
for /f "tokens=*" %%F IN ('dir M: "%%~f"') Do (
for %%N in ("%%F") Do (
set name=%%~NN
set ext=%%~XN
)
copy "%%~F" "%dest%\!name!_!i!!ext!"
set /A i=!i!+1
)
)
ENDLOCAL
We can just do a check if file exists and copy it:
#echo off
set "dest=C:\Users\kduquette.000\Desktop\Files"
for /f "delims=" %%i in (C:\Desktop\Files\list.txt) do if exist "M:\Cads\%%i" echo copy "M:\Cads\%%i" "%dest%"
Note, for now, I added echo to the copy string, so you can test the result first. Once happy with the results, remove echo
If however you want to search for the files, recursively throughout M:\ drive then:
#echo off
set "dest=C:\Users\kduquette.000\Desktop\Files"
for /f "delims=" %%i in (C:\Desktop\Files\list.txt) do (
pushd M:\
for /f "delims=" %%a in ('dir /b /s "%%i"') do echo copy "%%~fa" "%dest%"
popd
)

Copy files based on the extension length of the file?

i'm looking for a way on Windows to find all files with a specific file extension length and copy them to another location while preserving the folder structure.
For example lets say that I want to copy all files on my D: drive, with a file extension length of excatly six (*.******) and copy them to another location while also keeping the folder structure.
Is this possible in CMD?.
C:\Users\PeterR>copy C:\Users\PeterR\Documents\cmd\???.txt C:\Users\PeterR\Documents\cmd1\
--use ? to specify the lentgh. for six characters it's ??????.extension
What about the following code snippet:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_SOURCE=D:\"
set "_DESTIN=E:\"
pushd "%_SOURCE%" || exit /B 1
for /F "delims=" %%F in ('
xcopy /L /E /I ".\*.*" "E:\" ^| find ".\"
') do (
for /R "D:\" %%F in ("*.*") do (
set "EXT=%%~xF"
setlocal EnableDelayedExpansion
if "!EXT:~6!"=="" if not "!EXT!"=="!EXT:~5!" (
endlocal
move /Y "%%~F" "%_DESTIN%\%%~F"
) else endlocal
)
popd
endlocal
exit /B

Extract folder name from path in batch file

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

Modifying variable in a for loop batch file

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%
)

Resources