# DOS - show files in subdirs with quotes



## tuxalot (Dec 31, 2009)

Hi all. Pulling my hair out and I don't have much left. I'm creating a batch file that will do two things, the first of which is working. That is I want it to iterate through a directory tree and build a text file of the folder contents looking for zip files only. Easy enough with DIR, but I want quotes around the files it finds. I achieved this using this code:

```
for /r %inpath% %%g in (*.zip) do echo "%%g" >> textfile.txt
```
The resulting text file shows something like:

"C:\folderA\file1.zip"
"C:\folderA\folderB\folderC\file2.zip"
"C:\folderA\folderE\folderX\folderU\file3.zip"

So that bit is working. Now, I wish to use the same directory tree and build a second text file with a list of the zip file names contained within, but I want to strip out the folder tree and just list the zip file names. And the zips are on different levels as the above example shows. I'm guessing I'm to use something like:


```
for /f "tokens=* delims=" %%k in ('dir /s /b *.zip') do echo "%%~dpnk"
```
But that's not working... (and honestly, I'm not all that sure what the above means)

The text file should look something like:

"file1.zip"
"file2.zip"
"file3.zip"

These text files are being fed into another piece of software which requires this format.

Please help. I'll buy you an ice cream :wink:


----------



## tuxalot (Dec 31, 2009)

Oops, forgot to mention one thing...

As part of the solution, I would like to reformat how the zip file is presented. I need to break the zip file into parts and them re-assemble them in the text file. For example, the files use this naming convention:

parta-parta - partb - partc.zip

So my delimeters for the zip file would be "space hyphen space".

I would like the resulting text file to read (The quotes and parenthesis are intentional and should appear in the zip file):

"partb - partc (first two digits of parta).zip"

Thanks for looking and I appreciate any help.


----------



## TheOutcaste (Mar 19, 2009)

tuxalot said:


> ```
> for /f "tokens=* delims=" %%k in ('dir /s /b *.zip') do echo "%%~dpnk"
> ```


Got the wrong modifiers
you are using *dpn*
*Drive
Path
Name*
You just need *n*ame and e*x*tension:
*Echo "%%~nxk"*
(no spaces - the editor adds them with color sometimes)
This will parse the name and re-arraige it.
Set the path to the parent folder and to the output file in lines 3 and 4


```
@Echo Off
SetLocal EnableDelayedExpansion
Set _Source=C:\Temp Dir\Testzip
Set _OutFile=C:\Temp Dir\textfile.txt
If Exist "%_OutFile%" Del "%_OutFile%"
PushD "%_Source%"
For /F "Tokens=* Delims=" %%k In ('Dir /B /S *.zip') Do (
  For /F "Tokens=1,3,4 Delims=- " %%I In ('Echo %%~nk') Do (
    Set _First2=%%I
    Set _First2=!_First2:~0,2!
>>"%_OutFile%" Echo."%%J - %%K (!_First2!).zip"
    )
  )
PopD
```
I'm partial to Butter Pecan and Maple Nut:4-icescre

And, Welcome to TSF!


----------



## tuxalot (Dec 31, 2009)

Thanks to you, TheOutcaste. I read through your code. Looks like it will work. I'll try it tomorrow and report back.

Thanks again,

Tux.


----------



## tuxalot (Dec 31, 2009)

oops, I found out that changing file names by repositioning the parts is really reeking havoc on the app that these text files are fed into.

So I'll keep the names formatted as they are.

I have one more request to make this code really sing. Consider this file list:

fileA.zip
fileB.zip
fileC.ext1
fileC.ext2
fileD.ext1
fileE.ext1

Is it possible to add logic to the batch so the resulting text file would only show:

fileA
fileB
fileC

In other words, even though fileD and fileE are ext1, there is no matching ext2 so they are skipped, or in speaking terms, "find and index all zips. Also, index all ext1 but only if there is also an ext2 file present with the same name."

Way above my pay grade but hopefully someone here can offer some guidance.


----------



## tuxalot (Dec 31, 2009)

ok, here is one failed attempt:


```
for /r %inpath% %%a in (*.ext1) do CALL :Subroutine %%g
GOTO:EOF

:Subroutine
if exist "%%g.ext2" do echo "%%~ng"
pause
```
I'm new to coding so be nice :smile:


----------



## TheOutcaste (Mar 19, 2009)

Actually just need to add two lines to the previous code. Get a list of file *path\names* _without_ extensions using one of the extensions, then pipe *Dir* to *Findstr* and output only file path\names that exist in that list.

I'm assuming you only want to list files that have the same name and both extensions only if they are in the same folder.
So with these files:
Test\Folder1\FileA.ext1
Test\Folder1\FileA.ext2
Test\Folder1\FileB.ext1
Test\Folder1\FileC.ext1
Test\Folder1\FileC.ext2
Test\Folder1\FileD.ext1

Test\Folder2\FileA.ext1
Test\Folder2\FileA.ext2
Test\Folder2\FileB.ext2
Test\Folder2\FileC.ext1
Test\Folder2\FileC.ext2
Test\Folder2\FileD.ext2

You'll get this list:

FileA
FileC
FileA
FileC

Even though FileB and FileD exist with both extensions, the will not be included as they aren't in the same folder. If you do want them included, change this part of line 12 from this:
*Echo.%%~dpnk>>"%_tf1%"*
to this
*Echo.%%~nk>>"%_tf1%"*

Set the extensions in lines 5 and 6, I used .dat1 and .dat2 for testing.
I removed the code to re-arrange the file name and just output the zip file names.

```
@Echo Off
SetLocal EnableDelayedExpansion
Set _Source=C:\Temp Dir\Testzip
Set _OutFile=C:\Temp Dir\textfile.txt
Set _Ext1=.dat1
Set _Ext2=.dat2
Set _tf1=%~dp0\}t1{.}1{
If Exist "%_tf1%" Del "%_tf1%"
If Exist "%_OutFile%" Del "%_OutFile%"
PushD "%_Source%"
For /F "Tokens=* Delims=" %%k In ('Dir /A-D /B /S *.zip') Do Echo.%%nk>>"%_OutFile%"
For /F "Tokens=* Delims=" %%k In ('Dir /A-D /B /S *%_Ext2%') Do Echo.%%~dpnk>>"%_tf1%"
For /F "Tokens=* Delims=" %%k In ('Dir /A-D /B /S *%_Ext1%^|Findstr /I /G:"%_tf1%"') Do Echo.%%nk>>"%_OutFile%"
PopD
If Exist "%_tf1%" Del "%_tf1%"
```


----------



## tuxalot (Dec 31, 2009)

Your logic of what I'm after is right on, and the code is working. I had to put the tildes after the %% (%%~nk) to make it work - very nice and I appreciate the quick response.

Tux.


----------



## TheOutcaste (Mar 19, 2009)

Are there any **.zip* files in the source tree?

If there are no **.zip* files in the tree (current directory as set by the previous *PushD* statement and subfolders), *Dir* will output *File not found* to the screen. Nothing gets output to the file.

If you specify a nonexistent folder in the path for the output file (%_Outfile%) it would give this error instead:
*The system cannot find the path specified.*


----------



## tuxalot (Dec 31, 2009)

At times, the folders where this batch is run may or may not have zips, ext1 or ext2 files in them. So I'll have to add code for that (I'm guessing simply goto jumps) ? If this is the preferred method, I can handle that bit.

Thanks again!


----------



## TheOutcaste (Mar 19, 2009)

Now I'm getting the *%nk* in the output file. Have to figure out if a typo creeped in when I copied and pasted it


----------



## TheOutcaste (Mar 19, 2009)

Argh! found it. Left out the tilde
Line 11 and 13, should be %%~nk in the echo statement


----------



## tuxalot (Dec 31, 2009)

Yep, got that thanks. Now, I'm gonna add some choices to the batch and I also need to output anther text file listing the full path so I'm working on that now.

Also, I assume I can use:
Set _Source=%inpath%

I appreciate your assistance, Tux.


----------



## TheOutcaste (Mar 19, 2009)

If there are no files with the 2nd extension, the temp file used by *findstr* won't be created. That will cause *findstr* to fail. So a check for that file to skip the *findstr* line and will let it run even if there are no files. If you need something in the output file to say no files found, that can be done in a couple of ways.

This version will check to see if that file gets created.
I've also added the *2^>Nul*, which redirects the *File not found* message to Nul so it won't be displayed. This redirects all errors, so you may want to add it only when finished testing. You can also set that to a variable, and enable or disable it with just one line.


```
Set _ErrOff=2^>Nul
For /F "Tokens=* Delims=" %%k In ('Dir /A-D /B /S *.zip %_ErrrOff%') Do
```
Replace that set statement with *Set _ErrOFF=* and errors will be displayed

You can use *Set _Source=%inpath%*, or delete the *Set _Source* line, then replace *_Source* with *inpath* to use your variable.


```
@Echo Off
SetLocal EnableDelayedExpansion
Set _Source=C:\Temp Dir\Testzip
Set _OutFile=C:\Temp Dir\textfile.txt
Set _Ext1=.dat1
Set _Ext2=.dat2
Set _tf1=%~dp0\}t1{.}1{
If Exist "%_tf1%" Del "%_tf1%"
If Exist "%_OutFile%" Del "%_OutFile%"
PushD "%_Source%"
For /F "Tokens=* Delims=" %%k In ('Dir /A-D /B /S *.zip 2^>Nul') Do Echo.%%~nk>>"%_OutFile%"
For /F "Tokens=* Delims=" %%k In ('Dir /A-D /B /S *%_Ext2% 2^>Nul') Do Echo.%%~dpnk>>"%_tf1%"
If Not Exist "%_tf1%" Goto _Done
For /F "Tokens=* Delims=" %%k In ('Dir /A-D /B /S *%_Ext1% 2^>Nul ^|Findstr /I /G:"%_tf1%"') Do Echo.%%~nk>>"%_OutFile%"
:_Done
PopD
If Exist "%_tf1%" Del "%_tf1%"
```


----------



## tuxalot (Dec 31, 2009)

Looks good. I'll be testing the new code in a bit.

Thanks again,

Tux.


----------



## tuxalot (Dec 31, 2009)

For learning purposes, what does this line of code do?

Set _tf1=%~dp0\}t1{.}1{


----------



## tuxalot (Dec 31, 2009)

Also, can I put a progress bar of sorts in the code? The directories where this will run will have from 100 - 40,000 files to be processed. Would adding a progress bar slow the execution a lot?

As an option, if an actual progress bar won't work I would like to put in a line of test saying "...processing" or something. Where in the code would I put that?

Here is the working batch file (wonder why one cannot attach bat files?):


```
@ECHO off
SetLocal EnableDelayedExpansion
:: coded by Darin Redding et. al. 12/31/09
:: this script is made to run within the directory where your files exist.
:: alternatively a full path can be used by changing the Set _Source variable below to
:: Set _Source=C:\Program Files\...whatever
Set _Source=%inpath%
:: the kup file that contains the full paths
Set _OutFile1=C:\Program Files\SHCK\SHCKdocs\JBPAlbum2.kup
:: the kup file that contains the file names only
Set _OutFile2=C:\Program Files\SHCK\SHCKdocs\JBPAlbum.kup
Set _Ext1=.mp3
Set _Ext2=.cdg
:: no idea what these 2 lines of code do
Set _tf1=%~dp0\}t1{.}1{
Set _tf2=%~dp0\}t1{.}1{
If Exist "%_tf1%" Del "%_tf1%"
If Exist "%_tf2%" Del "%_tf2%"
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cls
goto _Start
:_BadChoice
cls
echo.
echo.
echo    " %choice% " is not valid please try again
echo.
:_Start
echo.
echo.
echo    SHCK FILE LIBRARY UPDATER
echo    =======================================================
echo.
echo    Please select 1 or 2:
echo.
echo    1 - This is the first time I've loaded songs into SHCK
echo    2 - I want to add files to my existing songlist
echo.
echo    3 - Quit
echo.
set choice =
set    /p choice=Please make your choice: 
echo.
echo. 
if not '%choice%'=='' set choice=%choice:~0,1%
if '%choice%'=='3' goto _Done
if '%choice%'=='2' goto _Jump1
if '%choice%'=='1' goto _Newlist
echo.
goto _BadChoice
:_Newlist
:: with choice 1 we want to delete the existing .kup files if they exist
If Exist "%_OutFile1%" Del "%_OutFile1%"
If Exist "%_OutFile2%" Del "%_OutFile2%"
:_Jump1
PushD "%_Source%"
For /F "Tokens=* Delims=" %%g In ('Dir /A-D /B /S *.zip 2^>Nul') Do Echo."%%g">>"%_OutFile1%"
For /F "Tokens=* Delims=" %%g In ('Dir /A-D /B /S *%_Ext2% 2^>Nul') Do Echo.%%~dpng>>"%_tf1%"
If Not Exist "%_tf1%" Goto _NoZips
For /F "Tokens=* Delims=" %%g In ('Dir /A-D /B /S *%_Ext1% 2^>Nul ^|Findstr /I /G:"%_tf1%"') Do Echo."%%g">>"%_OutFile1%"
:_NoZips
For /F "Tokens=* Delims=" %%k In ('Dir /A-D /B /S *.zip 2^>Nul') Do Echo."%%~nk">>"%_OutFile2%"
For /F "Tokens=* Delims=" %%k In ('Dir /A-D /B /S *%_Ext2% 2^>Nul') Do Echo.%%~dpnk>>"%_tf2%"
If Not Exist "%_tf2%" Goto _Done
For /F "Tokens=* Delims=" %%k In ('Dir /A-D /B /S *%_Ext1% 2^>Nul ^|Findstr /I /G:"%_tf2%"') Do Echo."%%~nk">>"%_OutFile2%"
:_Done
PopD
If Exist "%_tf1%" Del "%_tf1%"
If Exist "%_tf2%" Del "%_tf2%"
```
Thanks,

Tux.


----------



## tuxalot (Dec 31, 2009)

I have one issue. I need to order the text file in ascending alpha order.

Any idea if I can achieve this?

Tux.


----------



## TheOutcaste (Mar 19, 2009)

tuxalot said:


> For learning purposes, what does this line of code do?
> 
> Set _tf1=%~dp0\}t1{.}1{


That's just sets *_tf1* (*t*emp *f*ile *1*) to a temp file located in the same folder as the batch file
*%0* is the batch parameter that refers to the batch file itself
So *%~dp0* is the *d*rive and *p*ath to the batch file, meaning the same folder the batch file is in. This remains constant even if you change directories with *CD* or *PushD*
*t1.1* is just a temp file. I Add braces in a "reverse" order (close then open) just to reduce the likelihood you have a file of that name, hence *}t1{.}1{*

I did have a* _tf2* variable in one of my tests, but don't think I posted that version. Might have and edited it out, or did you add the *_tf2* lines?.
In the code you posted *_tf1* and* _tf2* refer to the same file, so *_tf2* isn't needed.



tuxalot said:


> Also, can I put a progress bar of sorts in the code? The directories where this will run will have from 100 - 40,000 files to be processed. Would adding a progress bar slow the execution a lot?
> 
> As an option, if an actual progress bar won't work I would like to put in a line of test saying "...processing" or something. Where in the code would I put that?
> 
> Here is the working batch file (wonder why one cannot attach bat files?):


It would slow it down, how much I don't know. Outputtng a character on the same line, like printing a period every few seconds or a rotating bar isn't something you can do with a simple batch statement, so would add quite a bit of time.
You could echo a message between each For loop. You could echo a period to the screen in each loop, that would put a period on a new line for each file, not very effective with lots of files. You can put the file name in the title par of the window though, but that can easily double the time of each loop, and usually is displayed so fast it's unreadable, but you can see that it's still doing something.

I see you have two Output files.
The code you posted does this if I'm reading it correctly:

Output FQPN of zip files, if any, into Output1
Output name only of zip files, if any, into Output2
Output name only list of files with both extensions into Output1
These will be after the list of zip files *only if* there are zip files
Output name only list of files with both extensions into Output2
These will be there whether or not there are zip files
They will be listed after the list of zip files.
FQPN=Fully Qualified Path Name, the drive, path, name, and extension of the file.

Seems to me this puts a mix into the Output 1 file, the FQPN of the zip files plus the name only list of files with both extensions.
Output2 will have the name only list of zip files and the name only list of files with both extensions.

Is that what you want?

Also, are there likely to be many more *.cdg* files than *.mp3*? Whichever is the fewest should be used for the first loop that creates the *_tf1* file; that will speed up the *findstr* part of the batch.

*.bat* is not in the list of allowed extensions is all. Guess the don't want executable files to be attached unless zipped or rarred. You can do that, or change the extension to *.txt* if you want to attach. Unless they are very long, best to just post them as you did.

Sort can be used to sort, but it doesn't always give the expected results, especially if numbers are in the name.
file10.zip will come before file2.zip for example.
I don't recall if it's case sensitive or not, haven't used it much.


----------



## tuxalot (Dec 31, 2009)

I removed the _tf2 code, thanks for that.



> Also, are there likely to be many more .cdg files than .mp3? Whichever is the fewest should be used for the first loop that creates the _tf1 file; that will speed up the findstr part of the batch.


There should be the same number of mp3 and cdg files. There are usually 95% zips and 5% mp3+cdg pairs (or less) in a typical directory.



> 1. Output FQPN of zip files, if any, into Output1
> 2. Output name only of zip files, if any, into Output2
> 3. Output name only list of files with both extensions into Output1
> These will be after the list of zip files only if there are zip files
> ...


Below is what I am looking to achieve as the final result (I added the sorting). So from top to bottom, the two output files should be identical except one has the FQPN and the other just the file name:

Output1:

FQPN of zip files, if any. FQPN of mp3 files _only if_ there is a cdg by the same name, if any. SORT files in ascending order by filename.

Output2:

Name only of zip files, if any. Name only of mp3 files _only if_ there is a cdg by the same name, if any. SORT files in ascending order by filename.

So that is the challenge. I can't see how it's possible to sort output1. The directory tree could be 2-5 levels deep.

I hope there is a solution.

Thanks for all your help thus far,

Tux.


----------



## TheOutcaste (Mar 19, 2009)

There's always a solution, but with batch might not be too swift.
If you start talking about manipulating GB size files, with a couple million lines, it takes time; lots of it if the file is bigger than the RAM your system has.

The file with just names shouldn't be too hard to sort, it's the one with the FQPN that will take the time.
Especially when appending to an existing file. If they were new each time there's a trick or two I think will work, but not if appending to an existing file.
Might need to use 4 files, two that are used for sorting, and the final output files
Looks like it's getting the correct info into each file, but don't need two sets of loops either, so that can be sped up. I'll look at that tomorrow.

Then see about sorting, that might take a day or three.

Edging up on three scoops of ice cream now...:grin:


----------



## tuxalot (Dec 31, 2009)

I wonder if VBS would be a better option.

3 scoops? More like a gallon


----------



## tuxalot (Dec 31, 2009)

Thinking more about this, what about this approach?

To summarize, the remaining goal is to sort Output1 and Output2. Output1 is FQPN of zip and mp3 files. Output2 is just a sorted list of filenames.

So if the code can produce a temporary outputX that looks like this:

file1.zip(a delimiter of some type)D:\folder1\folder2\folder3\etc...\file1.zip

Now, we can sort on file name and build outputX. After, we read outputX back into the script and split the data into two separate files at the delimiter yielding three files, outputX, Output1, Output2.

Output 1&2 are used by my app, and outputX remains in the app folder and is used to append new data to the list. To append files we add the new data to outputX per the format above as new lines, read outputX back in to the batch, sort, and overwrite Output1 and Output2.

Works good in my head, not so sure in code.


----------



## tuxalot (Dec 31, 2009)

So this is what I've done thus far:

```
PushD "%_Source%"
For /F "Tokens=* Delims=" %%g In ('Dir /A-D /B /S *.zip 2^>Nul') Do Echo."%%~ng"\#"%%~dpng">>"%_OutFileX%"
SORT "%_OutFileX%" > "%_OutFileXS%"
```
After, we read OutFileXS back into the script and split the data into two separate files at the delimiter (I chose \# as the delimiter) yielding Output1, Output2.

Now to figure out that bit.


----------



## TheOutcaste (Mar 19, 2009)

OK, I've tweaked it a bit to remove duplicate loops.
I was thinking the same thing as far as sorting goes.
Only problem would be if any of the file names in different folders would be duplicated. Also, numbers don't sort well unless they have the same number of digits, i.e., track10 comes before track2. Needs to be Track02 to sort correctly.

If you have two files with the same name, the sort will end up sorting by the drive and path. If the names will be unique in all folders, it will work.
With MP3s I'd expect them to be unique, unless a file name is just the Title -- could have same title on different albums or by different artists, so if that file is in different folders, the folder names would be the sort criteria

Should use just one character for the delimiter; a for loop won't handle two character delimiters.
For this I'd use a colon. It's not allowed in file names except right after the drive letter, so that's easy to account for, as that will be in the 2nd token.

Give this a try:

```
@Echo Off
SetLocal EnableDelayedExpansion
:: coded by Darin Redding et. al. 12/31/09
:: this script is made to run within the directory where your files exist.
:: alternatively a full path can be used by changing the Set _Source variable below to
:: Set _Source=C:\Program Files\...whatever
Set _Source=%inpath%
:: This file contains the list of zips with the names re-arraigned
Set _Outfile0=C:\Program Files\SHCK\SHCKdocs\Textfile.txt
:: the kup file that contains the full paths
Set _OutFile1=C:\Program Files\SHCK\SHCKdocs\JBPAlbum2.kup
:: the kup file that contains the file names only
Set _OutFile2=C:\Program Files\SHCK\SHCKdocs\JBPAlbum.kup
:: This file is used for sorting
Set _OutFile3=C:\Program Files\SHCK\SHCKdocs\SortFile.txt
Set _Ext1=.mp3
Set _Ext2=.cdg
:: Set temp file name, delete it if it exists
Set _tf1=%~dp0}t1{.}1{
If Exist "%_tf1%" Del "%_tf1%"
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Cls
Goto _Start
:_BadChoice
Cls
Echo.
Echo.
Echo    " %choice% " is Not valid please try again
Echo.
:_Start
Echo.
Echo.
Echo    SHCK FILE LIBRARY UPDATER
Echo    =======================================================
Echo.
Echo    Please select 1 or 2:
Echo.
Echo    1 - This is the first time I've loaded songs into SHCK
Echo    2 - I want to add files to my existing songlist
Echo.
Echo    3 - Quit
Echo.
Set choice =
Set /p choice=Please make your choice: 
Echo.
Echo. 
If Not '%choice%'=='' Set choice=%choice:~0,1%
If '%choice%'=='3' Goto _Done
If '%choice%'=='2' Goto _Jump1
If Not '%choice%'=='1' Goto _BadChoice
:: with choice 1 we want to delete the existing output files If they exist
For /L %%I In (0,1,3) Do If Exist "!_OutFile%%I!" Del "!_OutFile%%I!"
:_Jump1
PushD "%_Source%"
Echo Getting list of Zip Files, please wait.
For /F "Tokens=* Delims=" %%g In ('Dir /A-D /B /S *.zip 2^>Nul') Do (
>>"%_OutFile3%" Echo."%%~ng":"%%~g"
  For /F "Tokens=1,3,4 Delims=- " %%I In ('Echo %%~ng') Do (
	Set _First2=%%I
	Set _First2=!_First2:~0,2!
>>"%_OutFile0%" Echo."%%J - %%K (!_First2!).zip"
))
Echo Collating %_Ext1% and %_Ext2% files, please wait
For /F "Tokens=* Delims=" %%g In ('Dir /A-D /B /S *%_Ext2% 2^>Nul') Do Echo.%%~dpng>>"%_tf1%"
If Not Exist "%_tf1%" Goto _Done
For /F "Tokens=* Delims=" %%g In ('Dir /A-D /B /S *%_Ext1% 2^>Nul ^|Findstr /I /G:"%_tf1%"') Do (
>>"%_OutFile3%" Echo."%%~ng":"%%~g"
)
:_Done
PopD
If Exist "%_tf1%" Del "%_tf1%"
:: Sort the file, then parse it into the final files
Echo Sorting the file names
sort "%_OutFile3%" /O "%_tf1%"
Echo Creating the output files, please wait
For /F "Tokens=1* Delims=:" %%I In ('Type "%_tf1%"') Do (
>>"%_OutFile1%" Echo."%%~J"
>>"%_OutFile2%" Echo."%%~I"
)
:: Replace old sort file with the new one
Echo Cleaning up temp files, almost done
Copy /Y "%_tf1%" "%_OutFile3%">Nul
If Exist "%_tf1%" Del "%_tf1%"
```


----------



## TheOutcaste (Mar 19, 2009)

Added the Echo statements, then found a typo or two, make sure you refresh the page to get the corrected version


----------



## tuxalot (Dec 31, 2009)

Works great! Thanks so much for your effort. Here is some output for a folder containing zips only (I've not tried folders with mixed files or the append function yet):

```
Getting list of Zip Files, please wait.
'Messina' is not recognized as an internal or external command,
operable program or batch file.
'Tom' is not recognized as an internal or external command,
operable program or batch file.
'Shout' is not recognized as an internal or external command,
operable program or batch file.
'The' is not recognized as an internal or external command,
operable program or batch file.

etc...
```
Looks like it occurs only when there are two artists separated by an ampersand i.e. Captain & Tennille. Files are named Artist - Title. Doesn't seem to effect the batch.


----------



## TheOutcaste (Mar 19, 2009)

I was just thinking I should test to see if special characters would mess things up.
*&, %, !, <*, and *>* cause all kinds of fun with batch files.
I was hoping that since everything was quoted it wouldn't act up, but that doesn't always work.

Also, in the file name:
parta-parta - partb - partc.zip
if any of the partX portions contain spaces, the output of the re-arraigned names will be incorrect, as space is one of the delimiters. Works great to remove the spaces surrounding the dashes, but if the pieces contain spaces it won't work.
You can remove the space, but partb will have a leading and trailing space, and partc will have a leading space, so will need just a bit more code to account for that.

Let me create some different test files and see what i can figure out.


----------



## TheOutcaste (Mar 19, 2009)

OK, added some quotes in line 58, now handles files with & and % in the name. 

A single ! will be removed, but if there are two, everything in between them will be removed.

Removed the space as a delimiter, added lines 60 and 61, and modified what is now 62 and 63 a bit, so will handle names with spaces in the re-arraigning routine.


```
@Echo Off
SetLocal EnableDelayedExpansion
:: coded by Darin Redding et. al. 12/31/09
:: this script is made to run within the directory where your files exist.
:: alternatively a full path can be used by changing the Set _Source variable below to
:: Set _Source=C:\Program Files\...whatever
Set _Source=%inpath%
:: This file contains the list of zips with the names re-arraigned
Set _Outfile0=C:\Program Files\SHCK\SHCKdocs\Textfile.txt
:: the kup file that contains the full paths
Set _OutFile1=C:\Program Files\SHCK\SHCKdocs\JBPAlbum2.kup
:: the kup file that contains the file names only
Set _OutFile2=C:\Program Files\SHCK\SHCKdocs\JBPAlbum.kup
:: This file is used for sorting
Set _OutFile3=C:\Program Files\SHCK\SHCKdocs\SortFile.txt
Set _Ext1=.mp3
Set _Ext2=.cdg
:: Set temp file name, delete it if it exists
Set _tf1=%~dp0}t1{.}1{
If Exist "%_tf1%" Del "%_tf1%"
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Cls
Goto _Start
:_BadChoice
Cls
Echo.
Echo.
Echo    " %choice% " is Not valid please try again
Echo.
:_Start
Echo.
Echo.
Echo    SHCK FILE LIBRARY UPDATER
Echo    =======================================================
Echo.
Echo    Please select 1 or 2:
Echo.
Echo    1 - This is the first time I've loaded songs into SHCK
Echo    2 - I want to add files to my existing songlist
Echo.
Echo    3 - Quit
Echo.
Set choice =
Set /p choice=Please make your choice: 
Echo.
Echo. 
If Not '%choice%'=='' Set choice=%choice:~0,1%
If '%choice%'=='3' Goto _Done
If '%choice%'=='2' Goto _Jump1
If Not '%choice%'=='1' Goto _BadChoice
:: with choice 1 we want to delete the existing output files If they exist
For /L %%I In (0,1,3) Do If Exist "!_OutFile%%I!" Del "!_OutFile%%I!"
:_Jump1
PushD "%_Source%"
Echo Getting list of Zip Files, please wait.
For /F "Tokens=* Delims=" %%g In ('Dir /A-D /B /S *.zip 2^>Nul') Do (
>>"%_OutFile3%" Echo."%%~ng":"%%~g"
  For /F "Tokens=1,3,4 Delims=- " %%I In ('Echo "%%~ng"') Do (
	Set _First2=%%I
	Set _temp=%%J
	Set _temp=!_temp:~1!
	Set _First2=!_First2:~1,2!
>>"%_OutFile0%" Echo."!_temp! - %%K (!_First2!).zip"
))
Echo Collating %_Ext1% and %_Ext2% files, please wait
For /F "Tokens=* Delims=" %%g In ('Dir /A-D /B /S *%_Ext2% 2^>Nul') Do Echo.%%~dpng>>"%_tf1%"
If Not Exist "%_tf1%" Goto _Done
For /F "Tokens=* Delims=" %%g In ('Dir /A-D /B /S *%_Ext1% 2^>Nul ^|Findstr /I /G:"%_tf1%"') Do (
>>"%_OutFile3%" Echo."%%~ng":"%%~g"
)
:_Done
PopD
If Exist "%_tf1%" Del "%_tf1%"
:: Sort the file, then parse it into the final files
Echo Sorting the file names
sort "%_OutFile3%" /O "%_tf1%"
Echo Creating the output files, please wait
For /F "Tokens=1* Delims=:" %%I In ('Type "%_tf1%"') Do (
>>"%_OutFile1%" Echo."%%~J"
>>"%_OutFile2%" Echo."%%~I"
)
:: Replace old sort file with the new one
Echo Cleaning up temp files, almost done
Copy /Y "%_tf1%" "%_OutFile3%">Nul
If Exist "%_tf1%" Del "%_tf1%"
```


----------



## tuxalot (Dec 31, 2009)

hmmm... hangs at line 55 for approx. 15 seconds in a 2 level directory with only 180 files, proceeds to line 65 then prints the system cannot find file or folder specified...or something like that. I tried to set a pause to read through the error and I can't keep it from closing.


----------



## TheOutcaste (Mar 19, 2009)

Open a command prompt window, then run it from there. That way it will stay open.


----------



## tuxalot (Dec 31, 2009)

I copied your code again and pasted it into a new batch and it ran fine!

I'll continue testing mixed directories and appending, etc. Runs a little slower now but it _is _working and that's what matters at the end of the day.

It's going to take me a while to understand the code and I'm going through it now Googling bits here and there to try to learn this. I'm amazed that you were able to crank this code out so fast, very impressive.

ray:ray:ray:

Thank you so much for doing this.

Tux.


----------



## TheOutcaste (Mar 19, 2009)

Hmm, I don't see anything that would cause that, Works for me with 2 levels in two folders, both zip files only, or a mixture.

It looks like it would be one of the output lines, so let's turn Echo back on to see if it will show which line it is.

Add *Echo On* right after line 77 (Echo Creating the output files, please wait)
Then add* @Echo Off* after line 81 (the single *)* line) if you want.

Also, if you haven't done this already, in the Command Prompt right click the Title bar, click Properties. On the Layout tab, change the Screen Buffer size Height to 9999. You can change widow width as well, handy if you have a wide screen monitor,


----------



## tuxalot (Dec 31, 2009)

I think our posts crossed each other (see my edits above). I think all is well with the batch, and I thank you again for your assistance.

I'll post back after I've tested it a bit. Might be nice to add a time elapsed function at the end just for fun.

Tux.


----------



## TheOutcaste (Mar 19, 2009)

You're Welcome!

Your edit and my post have the same time stamp, so they definately crossed. Glad to hear it's working

Where you want to start timing add
*Set _Strt=%time%*
At the end:
*Echo End Time = %time%
Echo Start Time= %_Strt%*

Doing the math to calculate the difference can get quite involved; need to check if you passed midnight between start and end, remove leading zeros.
Then if you want to include the date, or time something that can take days, or work on any PC regardless of date/time format...
It can be quite educatiional.


----------



## tuxalot (Dec 31, 2009)

Setting an echo just after line 56 shows files written to Textfile.txt. What is the purpose of this file? Most of the lag seems to occur during this operation, while writing the other outfiles later on in the script is very fast. Here is an example entry in Textfile.txt:

"Band, - The ("A).zip"

The zip name is:

Allman Brothers Band, The - Ramblin' Man - 08.zip


----------



## tuxalot (Dec 31, 2009)

btw, I think I'll handle the issue of dup mp3's in different folders by appending the folder name to the end of the title. That should take care of it and I have a app that does that very efficiently. Also, sorting is working very well and below is an example of OutFile2:

"01 a test zip"
"1 a test zip"
"10 a test zip"
"2 a test zip"
"3 a test zip"


----------



## TheOutcaste (Mar 19, 2009)

tuxalot said:


> Setting an echo just after line 56 shows files written to Textfile.txt. What is the purpose of this file? Most of the lag seems to occur during this operation, while writing the other outfiles later on in the script is very fast. Here is an example entry in Textfile.txt:
> 
> "Band, - The ("A).zip"
> 
> ...


Textfile.txt contains the re-arraigned file names as you defined it in this post:


tuxalot said:


> As part of the solution, I would like to reformat how the zip file is presented. I need to break the zip file into parts and them re-assemble them in the text file. For example, the files use this naming convention:
> 
> parta-parta - partb - partc.zip
> 
> ...


The file name doesn't fit that pattern, and I forgot to remove the space as a delimiter in line 58 (Delims= " should be Delims="), so what happens is this:
parta="Allman
parta=Brothers
Partb=Band,
partc=The
Which should result in this
"Band, - The (Al).zip"

If line 62 has !_First2:~0,2! instead of !_First2:~1,2! that would explain the ("A) instead of (Al).

I copied the code and after removing the space in line 58 and adding that file name, the file name will break down like this (spaces after the = are part of the token):
parta="Allman Brothers Band, The
parta= Ramblin' Man
Partb= 08"
partc= missing
So the Result should have been
"08" - (Al).zip"

I was guessing the format was:
track-track - artist - title and you wanted artist - title (track#) as the name.
If the file names don't fit that *exact* format, 4 pieces separated by hyphens, that section of code won't be useful, and can be removed. This will be the slowest part of the code, as it has to manipulate each file name to re-arrange the pieces.

For something like this, there are many renaming programs that can rename the file based on the ID2/ID3 tags and won't care about the original file name. They ca also easily add a leading zero to the track numbers, so sorting will be correct, and 10 won't come before 2 as in your example.

To remove that section, remove the *Set _OuFile0=* line (#9), and change the section starting at line 52 to this:

```
For /L %%I In (1,1,3) Do If Exist "!_OutFile%%I!" Del "!_OutFile%%I!"
:_Jump1
PushD "%_Source%"
Echo Getting list of Zip Files, please wait.
For /F "Tokens=* Delims=" %%g In ('Dir /A-D /B /S *.zip 2^>Nul') Do Echo."%%~ng":"%%~g">>"%_OutFile3%"
Echo Collating %_Ext1% and %_Ext2% files, please wait
```
If you want a list with the title in a different format, you need to know the exact pattern. You can account for different delimiters, like - or _ easily, but the number and position of each piece (field actually) has to be consistent, or there has to be something unique in each field to identify what it is.


----------



## tuxalot (Dec 31, 2009)

Thanks Outcaste. I removed the code to re-arrange the file names for the time being and it's running well. Unfortunately I'm having an issue that will most likely need to be solved by the developer of the VB app that these output files serve.

Being a jukebox app, the user selects a song to play from a list via a touch screen. The list that is seen by the user is _OutFile2 in our batch file (filename only). Once selected, the file is served by _OutFile1 (which shows the FQPN).

The app was designed to hold all files in a single directory. I figured if _OutFile1 was comprised of files in a tree structure that they would be served properly. Instead the wrong song plays, or the program throws an error (calls the mp3 a bad file). I figure this is happening because the path cannot be found.

The output files that the app generates and those from this batch file are identical when building the outfiles from a _single _directory. When the app appends the songlist the mp3's are transferred to a single directory and the outfiles are regenerated. The files are added to the outfiles in a seemingly random order, intermixed within the original files. Of course when I create or append the outfiles I introduce a multi-tiered folder structure to _OutFile1 and the files are arranged in alpha order according to the batch code.

So in summary, I don't think the _ sort order _of the outfiles is important after all. I guess knowing the logic that the app uses to serve files based on user input is the missing link in getting files served from a directory tree.

Frustrating to say the least. Hopefully the app developer can offer some assistance.

Tux.


----------



## TheOutcaste (Mar 19, 2009)

The developer is going to be the one who can answer this. Could be the program expects them to all be in the same folder, and even though the path is included in the file, it's stripping the path from the FQPN leaving just the file name, and just checking the single directory for the name.

Good luck, hopefully they can explain the process so you you can do what you want to do.


----------

