Page 1 of 2

Renaming recursively files with alphabetical order

Posted: 15 Dec 2016 18:42
by crazyroot
Hello again,

Like I said in JREN topic, I'm trying to rename recursively files with alphabetical order to give a right order to a car radio. I need to have incrementing continued beacause tha car radio mix all songs. My code is like this :

Code: Select all

set zero=000
REM for /f "delims=" %%a in ('dir "E:\" /b /o:n') do (
for /r "E:\"  %%a in (.) do (
 pushd "%%a"
    for /f "delims=" %%j in ('dir /b/a-d/on ^| findstr /ile ".flac .mp3"') do set VrOldName=%%j& set VrFile=%%~nxj& set /a Nincr+=1& call :renaming
  popd)
:renaming
if /i %Nincr% GTR 9 set zero=00
if /i %Nincr% GTR 99 set zero=0
if /i %Nincr% GTR 999 set zero=
ren "%VrOldName%" "%zero%%Nincr%_%VrFile%"


I still didn't find how to get the right order for directories as for /r doesn't sort like 'dir "E:\" /b /o:n'.

Also, jren.bat would almost work except the incrementing and ordering problems. I tried of course :

Code: Select all

 jren "(.*)(\.mp3|\.flac)$" "$n+'_'+$1+$2" /nbeg 1 /npad 4 /j /i /s /pm "/p:**"


So, if you can give me some alternatives, I would be very happy ;)
Cheers

EDIT : jren v2.7 and its /nkeep option solved incrementing problem, BIG THANKS to Dave !!

Re: Renaming recursively files with alphabetical order

Posted: 21 Dec 2016 13:45
by crazyroot
Hello,

I'm still stucked with the sorting problem (folders and files in alphabetical order).
Reading other topics here I saw some of you proposing powershell which I have never used but by searching a little maybe it's the best tool for my problem ?
Something like :

Get-Childitem E:\ |
Foreach-object {
$a=$_.FullName
$a2=$_.BaseName
$b=something_that_increments_with_pad_4()+$a2
Rename-Item -path $a -NewName $b
}

With option -whatif which is really cool for testing. But I have many holes here : recurse subfolders, filters .mp3 and .flac, sorting folders, sorting files
As I had no luck with dos, maybe a big powershell loving heart here can help me ;) ?

Thanks and cheers

PS : maybe this could be closer?
Dir E:\*.mp3 *.flac -recurse | rename-item -newname { [io.path]::something_that_increments_with_pad_4()+GetFileName() }

Re: Renaming recursively files with alphabetical order

Posted: 21 Dec 2016 16:49
by ShadowThief
crazyroot wrote:I'm trying to rename recursively files

You're trying to do what now?

Re: Renaming recursively files with alphabetical order

Posted: 21 Dec 2016 17:42
by crazyroot
Hi ShadowThief,

Well still the same, I have a car radio that needs songs to be renamed but I want to keep the original order of songs (usually named 01. title1.mp3, 02 title2.mp3 etc) and it's the same with folders to keep the orders of artists and albums :
01. 1st artist
---------------01. 1st album of the 1st artist
---------------02. 2nd album of the 1st artist
--------------- ....
02. 2nd artist
---------------01. 1st album of the 2nd artist
---------------02. 2nd album of the 2nd artist
--------------- ....

The dos solution is almost OK on my post above, only folders are not sorted.
The jren 2.7 solution is OK with incrementing but folders are not sorted and even it's same with the files (regular expression cannot be sorted)
As noone has answered, I turned my attention to powershell but not knowing enough to conclude ;)

Hope I was clear enough, sorry for my bad english.

Re: Renaming recursively files with alphabetical order

Posted: 25 Dec 2016 14:23
by crazyroot
Merry Christmas to all members of dos-community ;)

Re: Renaming recursively files with alphabetical order

Posted: 26 Dec 2016 11:04
by pieh-ejdsch
Hello crazyroot,

Rekursive renaming of files and folders can occur only from the deepest folder.
Otherwise renamed folders do not exist any more -
- files are not found any more or in easy forLoop several flows are made.

A list must be provided and according to sorted.
with the help of this list the files and folders must be renamed.

Code: Select all

setlocal
set process=@echo ren
::set process=ren
set prompt=$g$s
set "Folder=e:\Music"
for /f "delims= " %%T in ('robocopy /L . . /njh /njs')do set "TAB=%%T"
for /f "tokens=*delims=1" %%x in ('
 ((for /l %%n in (1 1 9998^) do @echo :^) ^&robocopy /L /s /njh "%Folder%\." ".. ListOnly ..\." *.mp3 *.flac /fp /ns /nc /njs ^) ^
 ^|find ":" ^|findstr /n :\\ ^|findstr /b .....: ^|sort /r
 ')do @for /f "tokens=1*delims=:%tab% " %%o in ("%%x." )do %process% "%%p" "%%o_%%~nxp"

pause


[edit]
I have inserted afterwards the tabulator in the Script, he was eaten by the browser.
[/edit]

[edit2]
To create the prezeros automatically the smallest possible number of the preliminary lines is calculated.
Now for it a temporary file is used.
The echo is switched on before the last ForLoop, so that the command of renaming is also visible.
The count of the files and folders now occurs through the redirected output of Robocopy.
At the same time the temporary file with the same information is created.
If Robocopy error generates, these are indicated.
[/edit2]

Code: Select all

@echo off
setlocal
set "process=@echo ren"
rem set process=ren
set "Folder=d:\Music"
set "Files=*.mp3 *.flac"

 rem END Settings
set prompt=$g$s
for /f "delims= " %%T in ('robocopy /L . . /njh /njs')do set "TAB=%%T"
set "tempf=%temp%\RC_%time::=%"
for /f %%c in ('
 robocopy /L /s /njh "%Folder%\." ".. ListOnly ..\." %files% /fp /ns /nc /njs /log:"%tempf%" /tee ^|find /c "%tab%"
 ')do set /a C=%%c
set/as=1
<"%tempf%" (for /f "Delims=:" %%c in ('find "%tab%"^|findstr /n .^|findstr "^10*\>"')do set /a S=%%c,N=%%c+c,B=N/S)
for /l %%n in (0 %S% %N%)do set/a E=10*%%n-2
@echo on
@ <"%tempf%" (
for /f "tokens=*delims=%B%" %%x in (
 ' ((for /l %%n in (1 1 %E%^)do @echo -^) ^&find "%tab%" ^)^|findstr /n : ^|findstr /b %B% ^|sort /r
 ')do @for /f "tokens=1*delims=:%tab% " %%o in ("%%x." )do %process% "%%p" "%%o_%%~nxp"
) ||>&2 type "%tempf%"
@echo off
pause
exit /b


Phil

Re: Renaming recursively files with alphabetical order

Posted: 27 Dec 2016 12:17
by crazyroot
Wow Phil, thank you very much, your code is beautiful !
I didn't know robocopy was so powerfull, I'm very impressed.
Also, your loops and pipelines are great, you even renamed the folders by keeping alphabetical order, really fabulous !
I haven't still understand how everything works, but I will look it closer.
Thank you again I'm very happy with this !
Big hugs !!

Re: Renaming recursively files with alphabetical order

Posted: 29 Dec 2016 05:19
by crazyroot
I have just discovered the 2nd version, thank you so much Phil !

Is it possible to make some changes in 2nd version in order to :

1. increment folders independentely from files with pad=2, starting by 01 for folders and pad=4, starting by 0001 for MusicFiles

Code: Select all

ex : 01_Folder1, 02_Folder2,... /// 0001_MusicFile1, 0002_MusicFile2...


2. do not increment subfolders (stay with the same number) while there are zero MusicFile inside :

Code: Select all

ex :
   04_FolderTitleArtist
             |_    04_SubFolderTitleAlbum
                     |_   05_AlbumCD1
                            000n_MusicFilex1
                            000n+1_MusicFilex2
                            ....
                     |_   06_AlbumCD2
                            000m_MusicFiley1
                            000m+1_MusicFiley2
                            ....


Thank you again for your awesome work !

Re: Renaming recursively files with alphabetical order

Posted: 29 Dec 2016 19:09
by pieh-ejdsch
you want so

Code: Select all

@echo OFF
setlocal
set "process=@echo ren"
rem set process=ren
set "Folder=d:\music"
set "Files=*.mp3 *.flac"
 rem Setting Directory and File prezero
set /a DN=100 ,FN=10000

 rem END Settings
set prompt=$g$s
for /f "delims= " %%T in ('robocopy /L . . /njh /njs') do set "TAB=%%T"
set "tempf=%temp%\RC_%time::=%"
set /a DN*=10 ,DN+=1 ,FN*=10
 rem If Error stop
>"%tempf%L" robocopy /L /s /njh "%folder%\\" ".. ListOnly ..\\" %files% /fp /nc /bytes /njs
if errorlevel 16 type "%tempf%L" &del "%tempf%L" &pause &exit /b
@ <"%tempf%L" >"%tempf%" (
  for /f "skip=1tokens=1-3delims=%tab%" %%D in ('find "%tab%"')do @(
    if :%%F==: (set "Fname=%%E"
      set /a P=DN
      set "B= "
      for /f "delims=0 " %%n in ("%%D")do @set /a DN+=1
    )
    if NOT :%%F==: (set "Fname=%%F"
      set /a FN+=1 ,P=FN
      set "B="
    )
    setlocal enabledelayedexpansion
    for /f "delims=" %%L in ("!B!!P:~2! !Fname!.")do @endlocal&echo %%L
  )
)
del "%tempf%L"
@echo on
@for /f "tokens=1*" %%i in ('sort /r "%tempf%"')do %process% "%%~j" "%%i_%%~nxj"
@echo OFF
del "%tempf%"
pause
exit /b


Phil

Re: Renaming recursively files with alphabetical order

Posted: 30 Dec 2016 12:05
by crazyroot
Hi Phil and thank you for your very quick answer ;)

Well, this code seems to be very close to be perfect but I encountered an issue : files cannot be renamed as their path contains folders' names before renaming.
Maybe renaming files should be done juste before folders ?

Also, when testing with many folders, I've noticed that for artists and songs (folders and files) that are in foreign language (chcp different from the default), renaming fails. Don't know if this could be trapped and dynamically corrected ?

Re: Renaming recursively files with alphabetical order

Posted: 30 Dec 2016 13:59
by Aacini
Excuse me. The first time I read this request I just didn't understood the purpose. How a renaming could be done in alphabetic order if you add a number to the original names? The description "Like I said in JREN topic" serve for nothing, and show code that does not get the required result is not useful either... You should describe your problem in a clear and concise way and show a small example of the input and the desired output. Did you read the post placed at first place in the list of topics?

When I read your reply with an example of the desired final names, I assumed that what you want is "add a numeric prefix to the names in the order displayed by DIR command". If so, then this Batch file may solve your problem:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

rem Folders will have a two-digits numeric prefix
rem Folders prefix will increment for *ALL FOLDERS* in the tree
set "folder=100"
call :ProcessThisFolder
goto :EOF


:ProcessThisFolder

echo/
echo Folder: %cd%

rem Rename the files in this folder
rem Files will have a four-digits numeric prefix
rem Files prefix will *RESET TO ZERO* in each folder
set "file=10000"
for /F "delims=" %%f in ('dir /A:-D /B 2^>NUL') do (
   set /a file+=1
   ECHO ren "%%f" "!file:~1!_%%f"
)

rem For each subfolder in this folder:
for /F "delims=" %%d in ('dir /A:D /B 2^>NUL') do (
   rem Process it recursively
   cd "%%d"
   call :ProcessThisFolder
   cd ..
   rem Rename it
   set /A folder+=1
   ECHO ren "%%d "!folder:~1!_%%d"
)
exit /B

This basic program may be modified in several ways, like use the same increasingly numeric prefix in all files (instead of reset it to zero in each folder), reset the folder prefix to zero in each subfolder, check if a folder have no files in order to supress its renaming, etc.

Note that the REN commands have an ECHO command before, so the commands are just displayed in the screen. Note also that this program eliminate exclamation marks from file/folder names; this point may be fixed, if needed.

Antonio

Re: Renaming recursively files with alphabetical order

Posted: 30 Dec 2016 16:03
by crazyroot
Hi Antonio,

Thank you for your posting and your very interesting recursif code.

And so sorry for confusion, I should insist more in the description. My car radio is windows ce based and for some strange reasons, unlike classic mp3/flac readers, the car radio mix all the songs (*.mp3 *.flac) without consideration for folders but only alphabetical order of music files.

That's why, in order to let the car radio read in the right and controlled order for songs, I wanted to combine these features :
- filtering (*.mp3 *.flac)
- sorting folders and subfolders (to get an album in order)
- renaming music files with absolute incrementing (not interrupting), following the order of an album but also of the folders/subfolders, between albums

Phil gave me a working solution, but I have asked him some bonus features (renaming folders and subfolders with songs only), so the last solution he gave had an issue.

I like very much your recursif way Antonio, it solves sorting problem beautifully.
In this version however, there is no filter (mp3/flac, it would rename everything) and the modifications you enumerated (absolute increasing for numeric prefix and conditions on folder/subfolder prefix).
Thank you Antonio and again sorry for the misunderstanding before.

Re: Renaming recursively files with alphabetical order

Posted: 30 Dec 2016 18:56
by Aacini
@crazyroot,

Mi example code list all files. If you want to list .mp3 and .flac files only, just add the appropriate wild-cards to the DIR command: dir /A:-D /B *.flac *.mp3

If you want to rename all music files with just one continuous number sequence, move the initialization of file numbers from its current place, below "rem Files prefix will *RESET TO ZERO* in each folder", to the beginning, below "rem Folders prefix will increment for *ALL FOLDERS* in the tree". BTW the purpose of the REMarks is that you know what the commands does so you may complete your own modifications in the code, like this one.

If you want to rename folders with songs only, a small modification is required. However, in order to make this mod simpler, I assumed that the topmost folder, the one where the Batch file start run, does not contain song files. Note that this point is not contrary to the specifications, because you did not stated any specification! :wink:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

rem Folders will have a two-digits numeric prefix
rem Folders prefix will increment for *ALL FOLDERS* in the tree
set "folder=100"

rem Files will have a four-digits numeric prefix
rem Files prefix will increment for *ALL FILES* in the tree
set "file=10000"

call :ProcessThisFolder
goto :EOF


:ProcessThisFolder

rem For each subfolder in this folder:
for /F "delims=" %%d in ('dir /A:D /B 2^>NUL') do (
   rem Enter to it
   cd "%%d"

   rem Rename the music files in this folder
   set "anyFileHere="
   for /F "delims=" %%f in ('dir /A:-D /B *.flac *.mp3 2^>NUL') do (
      set /a file+=1
      ren "%%f" "!file:~1!_%%f"
      set "anyFileHere=1"
   )

   rem If this folder contain any music file
   if defined anyFileHere (
      rem Rename the folder
      set /A folder+=1
      cd ..
      ren "%%d" "!folder:~1!_%%d"
      cd "!folder:~1!_%%d"
   )

   rem Recursively process this folder
   call :ProcessThisFolder

   rem And go back to parent
   cd ..
)
exit /B

Antonio

Re: Renaming recursively files with alphabetical order

Posted: 31 Dec 2016 03:57
by crazyroot
Hi Antonio,

This version is almost perfect, thank you !

And you're right, I didn't specified completely the thing about folders/subfolders.
About the root folder, OK to asume there are no MusicFiles directly there, only via folders and/or subfolders.

Also, your last example code escapes renaming any folder/subfolder when no MusicFile there directly : there is a condition to add here, because a folder that has at least one subfolder which has MusicFile should be renamed also, and without increasing the FolderPrefix except if it's the first folder of the branche, see my "specification" post ;), 2nd point : http://www.dostips.com/forum/viewtopic.php?p=50684#p50684

About the cases when rename fails :
- I confirm that an exclamation mark is needed (there are some songs that had it in the name)
- I've already asked but I re-tape it here --> Also, when testing with many folders, I've noticed that for artists and songs (folders and files) that are in foreign language (chcp different from the default), renaming fails. Don't know if this could be trapped and dynamically corrected ?

Many thanx for your work and wish you and all dostips' community an excellent New Year's Eve ;)

Re: Renaming recursively files with alphabetical order

Posted: 01 Jan 2017 15:48
by pieh-ejdsch
If the file list is given in a simple ForLoop, the file name is always right.

The file name is falsified only by a For/f loop at name.
This can be simply tested

Code: Select all

 for /r D:\music %i in (*) do @for /f "delims=" %A in ('dir /s /b "%i"' ) do @if not exist %A echo %A not found!


Because the list with a diversion is made this list can spend just one wrong result.
The files are provided in a temporary folder help of Robocopy as zero byte files.
The files are provided alphabetically.
Now the file list is given by a simple ForLoop and in the orginal folder the files are renamed.

Code: Select all

@echo OFF
setlocal
set "process=echo ren"
 rem set process=ren
set "Folder=d:\mmtest"
set "Files=*.mp3 *.flac"
 rem Setting Directory and File prezero
set /a DN=100 ,FN=10000

 rem this is a temporary Folder for Sorting and renaming only
set "tempFolder=%temp%\nonExistingFolder"

 rem use call with copies for testing
 rem call :seperate
if :SUB==only * You want test with seperate Files * & @(
:seperate
rd /s /q "%folder%" 2>nul >nul
md "%folder%"
robocopy /create /mir D:\music "%folder%" /njh /fp /ndl /nfl /njs
exit /b
)

 rem END Settings
rd /s /q "%tempfolder%" 2>nul >nul
md "%tempfolder%"
call :subST_LW Q "%%folder%%"
call :subST_LW R "%%tempfolder%%"
if errorlevel 3 pause &exit /b 1
set Substlist= %Q% %R%
echo temporary Folder is filled ...
robocopy /create /mir %Q% %R% /njh /njs /ndl /nfl
pushD %R%
echo Rename ...
call :process
popD
for %%S in (%SubstList% )do subst /D %%S
rd /S /Q "%tempfolder%"
echo END script
pause
exit /b

:process
@set "D="
@for %%F in (%files%)do @( set/aFN+=1,D=1
  setlocal enabledelayedexpansion
    for %%N in (!FN:~1!)do @( endlocal
      if NOT exist %Q%%%~pnxF >&2 echo file %Q%%%~pnxF not found!
      if exist %Q%%%~pnxF %process% "%Q%%%~pnxF" "%%N_%%~nxF"
    )
  )
)
@if defined D set/aDN+=1
@for /D %%D in (*)do @( pushd %%D
  if not errorlevel 1 (
      call :process
      popD
      setlocal enabledelayedexpansion
      for %%N in (!DN:~1!)do @( endlocal
        if NOT exist %Q%%%~pnxD >&2 echo DIR %Q%%%~pnxD not found!
        if exist %Q%%%~pnxD %process% "%Q%%%~pnxD" "%%N_%%~nxD"
      )
    )
  )
)
@exit /b

:subST_LW outVar_LW VarPathToSubst
set "%1="
set "FreeDrive=Z Y X W V U T S R Q P O N M L K J I H G F E D C B A"
for %%i in (%FreeDrive%) do @if not defined %1 >nul subst %%i: %2 &&set %1=%%i:
if not defined %1 1>&2 echo Kein Freies Laufwerk gefunden!& exit /b 3
exit /b


Phil