i need take paths from txt and get last folder name and then use it.
setlocal EnableDelayedExpansion
set InputFile=somar.txt
for /f "tokens=* delims=" %%x in ('Type "%InputFile%"') do (
set path=%%x
:shift
for /f "tokens=1* delims=\/" %%i in ( "!path!" ) do (
set folder=%%i
set path=%%j
)
if not [!path!] == [] goto :shift
echo folder: !folder!
)
endlocal
problem is that it works only for first line in txt. where is the problem?
You have a number of problems:
1) Your FOR loop is broken the moment you issue a GOTO. You will not get any more FOR loop iterations after GOTO. You could fix this by moving your GOTO loop into a subroutine and then CALL the subroutine from within your DO loop.
2) The PATH environment variable has a reserved meaning for Windows. You should never use that variable name for your own purposes, even if it is localized as you have it. It isn't worth tempting fate. Simply use a different variable name.
3) Perhaps not an issue with your data, but ! is a valid character for a file or folder name. Your expansion of FOR variables will corrupt names containing ! if delayed expansion is enabled. This can be fixed by toggling delayed expansion on and off as needed.
You also have a minor inefficiency - There is no need to use TYPE with your FOR loop. You can simply let FOR read the file directly. (unless the file is unicode)
You could take all the recommendations above, but there is a much simpler solution :-)
EDIT - change made to handle a path that ends with \
#echo off
set "InputFile=somar.txt"
for /f "usebackq eol=: delims=" %%A in ("%inputFile%") do (
for %%F in ("%%A\.") do echo folder: %%~nxF
)
The ~nx FOR variable modifiers directly give you the name and extension of the end of the path. Type HELP FOR from the command line to read about all the modifiers that are available to FOR variables.
For variable filenames:
#Echo OFF
:: By Elektro H#cker
set "File=File.ext"
Call :Get_paths "%InputFile%"
Pause&exit
:Get_paths
Set "AbsolutePath=%~dp1"
set "AbsolutePath=%AbsolutePath:\= %"
FOR %%# in (%AbsolutePath%) do (
Set "LastFolder=%%#"
Echo Folder: %%#
)
Echo Last Folder: %LastFolder%
GOTO:EOF
Output:
Folder: C:
Folder: Users
Folder: Administrador
Folder: Desktop
Last Folder: Desktop
For files:
#Echo OFF
:: By Elektro H#cker
set "File=test.txt"
For /F "Tokens=* usebackq" %%# in ("%FILE%") DO (
Set "AbsolutePath=%%~dp#"
Call set "AbsolutePath=%%AbsolutePath:\= %%"
CMD /Q /C "#FOR %%# in (%%AbsolutePath%%) do (Echo Folder: %%#)"
)
Pause&Exit
InputFile content must contains filename or folder.
ex)
D:\Test1 <= folder
D:\Test2\file.txt <= file
D:\Test3\01. folder <= folder but recognize file. that contain extension.
My code is:
SETLOCAL EnableDelayedExpansion
SET lastFolder=
SET InputFile=somar.txt
FOR /F %%F IN (%InputFile%) DO (
CALL :__GetFolderName "%%F"
#ECHO lastFolder: !lastFolder!
)
GOTO :EOF
:: ******************** Inner Batch
:__GetFolderName
IF "%~x1"=="" SET lastFolder=%~n1 & GOTO :EOF
SET dp=%~dp1
CALL :__GetFolderName "%dp:~0,-1%"
GOTO :EOF
:: ********************
ENDLOCAL
Result is:
lastFolder: Test1
lastFolder: Test2
lastFolder: Test3
Related
Everyone,
I'm trying to do a differential backup with svnadmin dump --incremental commmand. My idea is so basic, to read the multiple svn repositories using the command dir and to put into a text file called "input", to read it line by line and put into variables.
Get the last revision of the repositories with full backup script and write in a text file called "output" and put into a variables.
Everything is done, but I can't use the svnadmin dump because I need the variables (arrays) inside the loops. How can I do it? Please, help me, I tried so many times and doesn't work still ):
#echo off
cls
:: =================== CONFIG ============================================
:: Path of the dir containing your repos [Note Trailing slash]
SET repodir=E:\svn\repositorios
:: Path of the dir in which to create you dumps [Note Trailing slash]
SET repodump=E:\Backup\SVN
:: File to read (multiple directories)
SET "File2ReadInput=E:\Backup\SVN\input.txt"
SET "File2ReadOutput=E:\Backup\SVN\output.txt
SET "File2ReadOutputNew=E:\Backup\SVN\New\output_new.txt
:: =================== CONFIG ============================================
:: =================== SCRIPT ============================================
rem deleting old file output.txt
del E:\Backup\SVN\output.txt
rem deleting old file output_new.txt
del E:\Backup\SVN\New\output_new.txt
rem creating new file output.txt
for /f "delims=" %%f in ("E:\Backup\SVN\*.data") do type %%f >> E:\Backup\SVN\output.txt
rem creating input file
dir %repodir% /ad /b > E:\Backup\SVN\input.txt
rem reading input file
setlocal EnableExtensions EnableDelayedExpansion
for /f "delims=" %%a in ('Type "%File2ReadInput%"') do (
set /a count+=1
set "Line[!count!]=%%a"
)
For /L %%i in (1,1,%Count%) do (
echo "Var%%i" is assigned to ==^> "!Line[%%i]!"
echo E:\svn\repositorios\!Line[%%i]!
set REPO_NAME=!Line[%%i]!
:: getting new transactions to compare
for /F "delims=" %%g in ('svnlook youngest E:\svn\repositorios\!Line[%%i]!') do (
echo %%~g
) > E:\Backup\SVN\New\last_rev_!Line[%%i]!_new.data
)
:: creating a new file with new datas
for /f "delims=" %%h in ("E:\Backup\SVN\New\*.data") do type %%h >> E:\Backup\SVN\New\output_new.txt
rem reading output file (dento do segundo for porque eu preciso do !Line[%%i]!)
setlocal EnableExtensions EnableDelayedExpansion
for /f "delims=" %%b in ('Type "%File2ReadOutput%"') do (
set /a out_count+=1
set "Output[!out_count!]=%%b"
)
for /L %%n in (1,1,%out_count%) DO (
echo "Var%%n" is assigned to ==^> "!Output[%%n]:~0,-1!"
set PREVIOUS=!Output[%%n]!
)
for /F "delims=" %%u in ('svnadmin dump -r!Output[%%n]:~0,-1!:HEAD E:\svn\repositorios\!Line[%%i]! --incremental') do (
echo %%~u
)> > E:\Backup\SVN\svn_backup_diff_!Line[%%i]!.dmp
Without having seen fully through your code IMO lines 47..50 have an improper setting of the parentheses, try changing to:
(for /F "delims=" %%g in ('svnlook youngest E:\svn\repositorios\!Line[%%i]!') do echo %%~g
) > E:\Backup\SVN\New\last_rev_!Line[%%i]!_new.data
An editor like Notepad++ helps to find/visualize corresponding pairs of parentheses.
I have a folder containing many files named as such: JBMA_23456.docx, JMRI_21456.docx, CM_22554.docx, QUA_11224.docx. How do I create a sub-folder for each file bearing the same name as the file but without the .docx file extension? Additionally, I want to store the filename only as variables.
For example, I need to create a sub-folder named JBMA_23456 from the document
JBMA_23456.docx. Can anyone point me in teh right direction?
#echo off
for %%A in (*.docx) do if not exist "%%~nA" md "%%~nA"
This creates a folder with the same name as each .docx file.
View modifiers in for /? or in call /?. The n modifier is the name.
Path modifiers:
dpnx is drive, path, name and extension.
Here's an example batch file which attempts to perform the tasks as laid out in your question:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "BaseDir=C:\Users\Compo\Desktop\test"
Set "FileExt=.docx"
For /F "Delims==" %%A In ('Set var[ 2^>Nul') Do Set "%%A="
Set "i=0"
For /F "Delims=" %%A In ('Where "%BaseDir%":*%FileExt% 2^>Nul') Do (Set /A i+=1
Call Set "var[%%i%%]=%%~nA"
If Exist "%%~dpA%%~nA\" (Echo Sub-Folder %%~nA already exists in %BaseDir%
) Else (Set /P "=Creating sub-folder %%~nA in %BaseDir%"<Nul
MD "%%~dpA%%~nA">Nul 2>&1 && (Echo= was successful) || Echo= failed))
Set var[ 2>Nul
Pause
In order to use it, you would first ensure that the directory holding your files, (excluding any trailing backslash), is placed between the = and " on line 4, and the single file extension, (including the leading period, .), similarly on line 5.
It is not entirely clear what you are asking for...
Anyway, here is the code i made
echo off
chcp 65001
cls
for /f "usebackq delims=." %%0 in (`dir /b "*.docx"`) do (
set filename=%%0
md %filename%
)
cmd /k
It creates a new folder for every file. Feel free to ask if this was not what you expected
I have about 1000 images and they have name like "IMG-12223". I want to rename them to 1 2 3 4 ... 1000. How can I do that. I have written a batch script which list the files but I don't know how to rename each file. e.g. rename first image with name "IMG-12223" to 1 , second image with name "IMG-23441" to 2 and so on ...
for /r %%i in (*) do (
echo %c%
)
Here's the script. Just put the script in your folder and run it.
#echo off & setlocal EnableDelayedExpansion
set a=1
for /f "delims=" %%i in ('dir /b *') do (
if not "%%~nxi"=="%~nx0" (
ren "%%i" "!a!"
set /a a+=1
)
)
If you want to keep the extensions, i.e. rename "IMG-12223.jpg", "IMG-12224.jpg", etc to "1.jpg", "2.jpg", etc, you may use the following script.
#echo off & setlocal EnableDelayedExpansion
set a=1
for /f "delims=" %%i in ('dir /b *.jpg') do (
ren "%%i" "!a!.jpg"
set /a a+=1
)
[Update] Here're explanations for the lines mentioned in Jack's comment.
setlocal EnableDelayedExpansion
In general, we want the variable a to be delayed expansion when it's executed but not the line is read. Without it, the variable a cannot get its increased value but always 1.
For the detail of EnableDelayedExpansion, please refer to the answer https://stackoverflow.com/a/18464353/2749114.
for /f "delims=" %%i in ('dir /b *.jpg')
Here dir with /b option, lists only file names of all jpg files.
The for loop traverses and renames all jpg files.
For the delims option, since the default delimiter character is a space, without the option delims=, it fails with the image files with spaces in the file names. I.E. for an image file named "img with spaces.jpg", without the option, the value of %%i is "img" but not the whole name "img with spaces.jpg", which is incorrect.
For for loop, please refer to the page http://ss64.com/nt/for_f.html.
if not "%%~ni"=="%~n0"
I have change it to if not "%%~nxi"=="%~nx0" to be more accurate. And the codes attached have been updated.
It's actually used to avoid to rename the bat file itself. If we limit the renaming only upon "jpg" files, then the line is not needed.
%%~nxi is the file name with extension for each file traversed. And %~nx0 is the running bat file with extension. For details, please refer to the page DOS BAT file equivalent to Unix basename command?.
There is no need for a batch script. A simple one liner from the command line can do the job :-)
I use DIR /B to generate the list of files, piped to FINDSTR to number the files, all enclosed withn FOR /F to parse the result and perform the rename.
for /f "delims=: tokens=1*" %A in ('dir /b *.jpg^|findstr /n "^"') do #ren "%B" "%A%~xB"
Double the percents if you want to put the command in a batch script.
Try this, you have pair of namevalues in a text file then loop values and do the magic. Namevalues are separated by empty spaces. This allows you to map old->new filenames accordingly. Or you keep idx+1 counter and use it for new filenames.
keyvalue.bat
#echo off
set idx=0
for /F "tokens=1,2" %%A in (keyvalue.txt) do call :PROCESS "%%A" "%%B"
GOTO :END
:PROCESS
set var1=%~1
set var2=%~2
set /A idx=%idx%+1
echo %var1% goes to %var2% (%idx%)
GOTO :EOF
:END
pause
keyvalue.txt
file888.dat newfile1.dat
file333.dat newfile2.dat
file9.dat newfile3.dat
file01.dat newfile4.dat
I want to loop recursively through a directory and have it's filenames echoed.
I ran into the 1 vs 01 name trouble.
Say, I have this:
D:\Downloads\prefixorder\order\1.txt
D:\Downloads\prefixorder\order\10.txt
D:\Downloads\prefixorder\order\2.txt
D:\Downloads\prefixorder\order\3.txt
D:\Downloads\prefixorder\order\1\new.txt
D:\Downloads\prefixorder\order\10\new.txt
D:\Downloads\prefixorder\order\2\new.txt
D:\Downloads\prefixorder\order\order\1.txt
D:\Downloads\prefixorder\order\order\10.txt
D:\Downloads\prefixorder\order\order\2.txt
D:\Downloads\prefixorder\order\order\20.txt
D:\Downloads\prefixorder\order\order\3.txt
D:\Downloads\prefixorder\order\order2\1.txt
D:\Downloads\prefixorder\order\order2\10.txt
D:\Downloads\prefixorder\order\order2\2.txt
D:\Downloads\prefixorder\order\order2\20.txt
D:\Downloads\prefixorder\order2copy\1.txt
D:\Downloads\prefixorder\order2copy\10.txt
D:\Downloads\prefixorder\order2copy\2.txt
D:\Downloads\prefixorder\order2copy\20.txt
D:\Downloads\prefixorder\order3\1.txt
D:\Downloads\prefixorder\order3\10.txt
D:\Downloads\prefixorder\order3\2.txt
D:\Downloads\prefixorder\order3\20.txt
D:\Downloads\prefixorder\1.txt
D:\Downloads\prefixorder\10.txt
D:\Downloads\prefixorder\2.txt
and I want to have 10 listed below 1 in each folder (and the folder being sorted like this, too).
Basically looking like this:
D:\Downloads\prefixorder\1.txt
D:\Downloads\prefixorder\2.txt
D:\Downloads\prefixorder\10.txt
D:\Downloads\prefixorder\order\1.txt
D:\Downloads\prefixorder\order\2.txt
D:\Downloads\prefixorder\order\3.txt
D:\Downloads\prefixorder\order\10.txt
D:\Downloads\prefixorder\order\1\new.txt
D:\Downloads\prefixorder\order\2\new.txt
D:\Downloads\prefixorder\order\10\new.txt
D:\Downloads\prefixorder\order\order\1.txt
D:\Downloads\prefixorder\order\order\2.txt
D:\Downloads\prefixorder\order\order\3.txt
D:\Downloads\prefixorder\order\order\10.txt
D:\Downloads\prefixorder\order\order\20.txt
D:\Downloads\prefixorder\order\order2\1.txt
D:\Downloads\prefixorder\order\order2\2.txt
D:\Downloads\prefixorder\order\order2\10.txt
D:\Downloads\prefixorder\order\order2\20.txt
D:\Downloads\prefixorder\order2copy\1.txt
D:\Downloads\prefixorder\order2copy\2.txt
D:\Downloads\prefixorder\order2copy\10.txt
D:\Downloads\prefixorder\order2copy\20.txt
D:\Downloads\prefixorder\order3\1.txt
D:\Downloads\prefixorder\order3\2.txt
D:\Downloads\prefixorder\order3\10.txt
D:\Downloads\prefixorder\order3\20.txt
So somewhat the same order as the default any win7 explorer display sorted after ascending alphabet. (Though in that version the files of a root files get to show below the folders, but that doesn't really matter).
A nice bonus would be, that this output comes no matter what object I dragged the dropped it from.
I found this, which solves this problem nicely for one folder:
Read files in directory in order of filename prefix with batch?
The diffrence to that problem that I want this recursively and while multiple files/folders can be dropped.
My current (buggy) modification looks like this:
#echo off
setlocal EnableDelayedExpansion
rem Create an array with filenames in right order
if [%1]==[] goto :eof
:loop
for /f "tokens=* delims=" %%a in ('dir "%~1" /a-d /s /b') do (
for /F "delims=-" %%i in ("%%a") do (
set "number=00000%%~ni"
set "file[!number:~-6!]=%%a"
)
)
rem Process the filenames in right order
for /F "tokens=2 delims==" %%f in ('set file[') do (
echo %%f
)
shift
if not [%1]==[] goto loop
#pause
the most buggy line in question would seem to be
set "file[!number:~-6!]=%%a"
whose array parameter in fact I don't even really begin to understand. My guess anyhow is that the array's entries are overwritten in each loop, because the parameters are pretty much the same in each loop.
I had also supected that the %%~ni is probably the cause of the overwriting, since the filenames inside the folders are all the same. Using %%~ni seems to me pbviously wrong, but using %%i simply doesn't do any sorting anymore and echoes out 10 before 1, which is even more wrong.
It works however if multiple folders are dragged, since they are in seperate echo loops. I tried putting in the echo loop within the first outer loop before and after the first inner loop. While it does make it that nothing gets omitted, it's not sorting properly at all.
Back to the major question: how do I solve that recursively and with mutiple files/folders dragged, that sorts the filenames and foldernames.
foldernames weirdly are of no prolem when recursively in one folder. It become a problem, when multiple folders/files are dragged, since it then starts off with the dragged object as the first argument.
Do I need to use an array of arrays or something like that? (Tried looking into it, didn't really get how that is possible in batch, yet, through.) Or is there any other way to do this?
Not even sure this is what you need, but just if it can help ...
#echo off
:: Without arguments, just list current folder
if "%~1"=="" (
call :recursiveSortedFileFolderList "%cd%"
goto :eof
)
:: Else, create a list of elements to sort
set "tempFile=%temp%\%~nx0.tmp"
call :generateList %* > "%tempFile%"
call :recursiveSortedFileFolderList "%tempFile%"
del "%tempFile%" >nul
goto :eof
:generateList
echo(%~1
if not "%~2"=="" shift & goto :generateList
exit /b
:recursiveSortedFileFolderList startFolder
setlocal enableextensions disabledelayedexpansion
:: Prepare padding base
set "pad=#################################"
set "pad=%pad%%pad%"
set "pad=%pad%%pad%"
set "pad=%pad%%pad%"
:: paddings for numeric or alphabetic prefixed files and folders
set "_NPad=%pad%"
set "_APad=%pad:#=$%"
:: start work
call :_doRecursiveSortedFileFolderList "%~1"
:: cleanup and exit
endlocal
exit /b
:_doRecursiveSortedFileFolderList folder
:: adjust environment for current folder
setlocal
set "timestamp=%time::=%"
set "tempFile=%temp%\%~nx0.%random%%random%%random%%random%.%timestamp:,=%.tmp"
set "folder=%~1" & if not defined folder ( set "folder=." ) else ( set "folder=%~f1" )
:: determine if we are handling a folder or a file with elements in it
if exist "%folder%\" (
set "cmd=dir /b ""%folder%\*"" 2^>nul"
) else if exist "%folder%" (
set "cmd=more ""%folder%"" "
set "folder="
for /f "tokens=* usebackq" %%a in ("%folder%") do if not defined folder (
for /f "tokens=*" %%b in ("%%~dpa\.") do set "folder=%%~dpnxb"
)
) else (
endlocal
exit /b
)
:: For each element in the indicated folder/file, prefix it with the adequated prefix
:: depending if it is a file or a folder, and send the output to a temporary file
:: that will be sorted (using the adecuate prefix), and processed
(for /f "tokens=*" %%a in ('%cmd%') do (
:: determine if file or folder
if exist "%folder%\%%~nxa\" ( set "type=f" ) else ( set "type=a" )
:: determine correct padding
if "%%~na" geq "a" ( set "name=%_APad%:%%~na" ) else ( set "name=%_NPad%:%%~na" )
:: generate final padded record
setlocal enabledelayedexpansion
echo(!type!:!name:~-260!%%~xa
endlocal
))> "%tempfile%"
:: Sort the temporary file and for each element on it, if it is a file, echo to console,
:: else it is a folder and a recursive call is made to process it
for /f "tokens=1,2,* delims=:" %%a in ('sort /L "C" "%tempfile%"') do (
if "%%a"=="a" (echo(%folder%\%%c) else (call %0 "%folder%\%%c")
)
:: clean and exit
endlocal & del "%tempfile%" > nul 2>nul
exit /b
i am trying to get files from a directory and want to set names of the file to a variable using batch script.
this is my code .but it always setting same value to variable
can any body give solution
echo on
setlocal EnableDelayedExpansion
for /f %%x in ('dir /b C:\backup_dir') do (
SET test=%%~nx
if "%test:~0,6%"=="kdc_db" (set DUMP=%%x)
if "%test:~0,6%"=="kdc_ke" (set KEYS=%%x)
)
echo %DUMP%
echo %KEYS%
here dump and keys variables are always set to same value
You need to use delayed expansion. You have already enabled it, you just need to replace your %'s with !'s
echo on
setlocal EnableDelayedExpansion
for /f %%x in ('dir /b C:\backup_dir') do (
SET test=%%~nx
if "!test:~0,6!"=="kdc_db" (set DUMP=%%x)
if "!test:~0,6!"=="kdc_ke" (set KEYS=%%x)
)
echo %DUMP%
echo %KEYS%