1.

Solve : Retrieving filepaths from a directory and performing analysis on them.?

Answer»

Hi all,

I am writing a batch file which needs to retrieve a list of files from a directory (including subdirectories) and then performs analysis on each path. Currently though, I am unable to get it working. Rather than post the entire batch file, I have created a well-commented sample showing the method I am currently working on. If there is a better way of doing this, I'd be very happy to hear of it.

Code: [Select]echo on
rem Make an example directory and populate it with 5 files.
set d=%homedrive%\ExampleTestDir
If not exist %d% md %d%
echo/File 1 contents.>%d%/file1.txt
echo/File 2 contents.>%d%/file2.txt
echo/File 3 contents.>%d%/file3.txt
echo/File 4 contents.>%d%/file4.txt
echo/File 5 contents.>%d%/file5.txt

rem Create a set of variables from file_0 to file_x , where x is the number of files in the directory and all its sub-directories.
rem These variables will each hold the file path of one of the files in the directory tree.
set filecounter=0
for /f "delims=" %%a in ('dir/b /s %d%') do (
call set file_%%filecounter%%=%%a
set/a filecounter+=1
)

rem Now attempt to echo the variable values (essentially performing a dir/b /s).
set counter2=0
:loop
set filenumber=file_%counter2%
rem In the LINE of code below, I use 2>nul to prevent the script from throwing 'The process tried to write to a nonexistent pipe.' errors seemingly at random.
rem I would like to know why it does this and find a way of avoiding it, if possible.
echo/2>nul | echo/%%%filenumber%%%
set/a counter2+=1
If %counter2% GEQ %filecounter% goto breakout
goto loop


rem Now the above works (albeit with the erratic error messages if 2>nul is not used), but I cannot set a vairable to be equal to the output of the echo command.
rem For example, replacing 'echo/2>nul | echo/%%%filenumber%%%' with 'echo/2>nul | echo/%%%filenumber%%% | set curfilename=' does not work.
rem The example loop below (currently ignored) does not behave as expected (by me, at least).
rem Curfilename is not assigned a value.
:unusuedloop
set filenumber=file_%counter2%
echo/2>nul | echo/%%%filenumber%%% | set curfilename=
echo/%curfilename%
set/a counter2+=1
If %counter2% GEQ %filecounter% goto breakout
goto unusedloop

:breakout
rem And tidy up afterwards.
rd/s /q %d%

To clarify, when I say it produces these errors seemingly at random, I mean that the output from the exact same batch script (with the 2>nul removed) can produce the following:

Code: [Select]C:\ExampleTestDir\file1.txt
The process tried to write to a nonexistent pipe.
C:\ExampleTestDir\file2.txt
C:\ExampleTestDir\file3.txt
C:\ExampleTestDir\file4.txt
C:\ExampleTestDir\file5.txt
The process tried to write to a nonexistent pipe.
and

Code: [Select]C:\ExampleTestDir\file1.txt
C:\ExampleTestDir\file2.txt
The process tried to write to a nonexistent pipe.
C:\ExampleTestDir\file3.txt
C:\ExampleTestDir\file4.txt
The process tried to write to a nonexistent pipe.
C:\ExampleTestDir\file5.txt
With no alternations whatsoever to the batch file between the attempts.

Also, on a related note, when extracting the filename from the path (although I usually need the path, sometimes I need the name), I am using the cumbersome line
Code: [Select]for /f "delims=" %%a in ("%source%") do set sourcefilename=%%~nxawhere source is a filepath to the file. Although this works well enough, I can't help but feel there's a neater way of doing it. Is there?

Any thoughts MUCH appreciated, be they on my (rather poor) coding or direct answers to the questions.
Why???!!! are you doing this?

echo/2>nul | echo/%%%filenumber%%%

When you can do this?

call echo %%%filenumber%%%

See? No pipe!

And... get the value into a variable:

for /f "delims=" %%A in ('call echo %%%filenumber%%%') do set curfilename=%%A

Or... much simpler:

call set curfilename=%%%filenumber%%%

Quote

Also, on a related note, when extracting the filename from the path (although I usually need the path, sometimes I need the name), I am using the cumbersome line

for /f "delims=" %%a in ("%source%") do set sourcefilename=%%~nxa

where source is a filepath to the file. Although this works well enough, I can't help but feel there's a neater way of doing it. Is there?

I don't know why you call that "cumbersome". It's a one line method of getting the name and extension. That's about as "neat" as NT batch scripts get.

Question: If you feel the need to laboriously create pseudo-arrays, and you find batch syntax "cumbersome", why not use a language with PROPER arrays and cool looking code, like VBScript or, better, Powershell?

What is your objective with that script?
THANKS very much,  Salmon Trout, that does the job wonderfully.

I'm using this strange method because I'm that bad at writing batch files. If there's a better way of doing what I'm trying to, I'm happy to hear it, as I indicated in my first post.

The reason I chose to use a normal MS DOS batch file is because I've used them before. Not a particularly good reason, admittedly.

Quote from: Salmon Trout on January 05, 2012, 01:12:16 PM
"with the 2>nul removed" - did you mean like this?

echo/ | echo/%%%filenumber%%%


Yes, exactly.

As for why I'm doing this, the script will feed an unknown number of files into an application (amongst other things). As I've stated, the code I wrote was just an example showing what I was trying to achieve, without my putting the FULL code in.
See above! I edited my post while you were answering.
Quote from: Sirim on January 05, 2012, 01:51:23 PM
The reason I chose to use a normal MS DOS batch file is because I've used them before. Not a particularly good reason, admittedly.

A very poor reason coming from an apparently intelligent person!

By the way, this is not "MS-DOS".
please read multiple edits to my reply no.1 above
Your updated solution also works perfectly and is neater, thanks.

When I said it was cumbersome, I was referring to the way in which I'm essentially using the for statement to convert a normal variable into the %%[letter] form, so that I can then extract the filename using %%~nx[letter].

I'm only creating a pseudo-array because I can't think of a simpler way of doing it. Again, I emphasize that I'm not skilled at working with these files.

Quote from: Salmon Trout on January 05, 2012, 01:55:18 PM
A very poor reason coming from an apparently intelligent person!

By the way, this is not "MS-DOS".


Sorry. You're completely right on both counts. Would cmd.exe batch files describe them well enough? Quote from: Sirim on January 05, 2012, 02:25:16 PM
When I said it was cumbersome, I was referring to the way in which I'm essentially using the for statement to convert a normal variable into the %%[letter] form, so that I can then extract the filename using %%~nx[letter].

The FOR command was designed for exactly that kind of task. If you check the help (type FOR /? at the prompt) you will see all the ~ variable modifiers. They also work with single percent parameters, %0 (special) and %1 to %9

Quote
Would cmd.exe batch files describe them well enough?

Yes, or "NT family command scripts". Your code is not "bad" at all, it is very intelligent.


Discussion

No Comment Found