Link to home
Start Free TrialLog in
Avatar of TrishITGuru
TrishITGuruFlag for United States of America

asked on

How can I write the actual length of the folder/file name to the text file?

This script was able to count the number of characters in a path name and write any path length > 240 characters to a file.
What I need to know now is, how do I get the actual length (i.e. 250) to show up before or after the path?
I need the output to be as follows:
\\servername\share\folder1\folder2\longname1\another ridiculously long name\and even longer name that is going to take up too much space\here is my document.doc  Length=250

Thanks.
Avatar of Chris Bottomley
Chris Bottomley
Flag of United Kingdom of Great Britain and Northern Ireland image

Hello TrishITGuru,

in VBS then use: len("\\servername\share\folder1\folder2\longname1\another ridiculously long name\and even longer name that is going to take up too much space\here is my document.doc ")
or len(fullname)

Regards,

chris_bottomley
Avatar of TrishITGuru

ASKER

I know how to do it in VBS, but the .bat file is what was created.
Here is the .bat file, is there a line I can add to this code that will enter the length before or after the path name?

@echo off
REM Change to 160 columns wide
mode 160,5000
REM Save as findlong.cmd or whatever.  
if "%1"=="" goto :help
setlocal enabledelayedexpansion
set source=%*
echo Started at %time%
dir "%source%" /ad /s /b |sort /+206 /r > LongName.txt
for /f "tokens=*" %%a in (longname.txt) do (
set line=%%a
if not "!line:~205!"=="" (echo !line!) else (goto :next)
)
:next
echo.
echo Finished at %time%
Echo Found no. of files:
find /v /c "NOT-LIKELY" longname.txt
pause
exit /b
Ah, I answered because of the VBS domain!  I'm not particularly skilled but try this:

for %%a in (longname.txt) do set /a len=%%~za & set /a len -=2 & del "%temp%\st.txt"

it sets the value to teh variable len ... if the author is correct: http://forums.afterdawn.com/thread_view.cfm/514228

Chris
Avatar of Bill Prew
Bill Prew

Chris,

You're close, but missing a bit of the puzzle.  The trick here is that there is no easy way to determine the length of a string itself right in a BAT script, but it is easy enough to find out the size of a file on disk.  So, what we can do is create a new file on disk with just the variable that we want to find the length of echo'ed to it.  Then we get the size of the file, subtract 2 for the <cr><lf> that is added, and delete the temp file.  So I think the code needs to look something like this.

echo !line!>"%temp%\st.txt"
for %%A in ("%temp%\st.txt") do set /a len=%%~zA & set /a len -=2 & del "%temp%\st.txt"

~bp
TrishITGuru

To get the length of a filename (including it's full path) you need this:

   echo %filename%>length.txt
   for %%l in (length.txt) do set /a length=%%~zl-2
   echo %length%>file.txt

Let me explain (as this is my technique which I use universally).

First, you output the filename to a text file (length.txt)

   echo %filename%>length.txt

Noticse there is no space between %filename%, '>' and length.txt.

Now, the size (in bytes) of length.txt is simply the length of the filename + linefeed + carriagr return.

You need to get this size and assign it to a variable and at the same time, subtract 2 from it. Like this:

   for %%l in (length.txt) do set /a length=%%~zl-2

%%l would normally return just the filename (length.txt) however, %%~zl returns just it's size in bytes. Remember we need to subtract 2 from this, so we use SET /A to perform an arithmethmetic assignment. The variable %length% will be set to the size of length.txt - 2.

Finally, you can output this variable to a file like so:

   echo %length%>file.txt

So, the file file.txt now contains an integer equal to the length of the filename which was output to the file length.txt earlier.


Example:

This code does a DIR to fetch each filename in your source folder. The FOR-variable (%%a) picks up each filename in turn expanding it to it's full path/filename (%%~dpnxa) and outputing it to the file length.txt. The rest is as explained above. Here goes:


   for /f "tokens=*" %%a in ('dir /a-d /b %source%\*.*') do (
      echo %%~dpnxa>length.txt
      for %%f in (length.txt) do set /a !length!=%%~zf-2
         echo !length!>>file.txt
      )
   )

file.txt will contain a list of integers. I've used '>>' instead of just '>' so as to append each integer to the file. Notice the use of !length! instead of %length% - this is due to variable expansion issues while working with changing variable inside
TrishITGuru

To get the length of a filename (including it's full path) you need this:

   echo %filename%>length.txt
   for %%l in (length.txt) do set /a length=%%~zl-2
   echo %length%>file.txt

Let me explain (as this is my technique which I use universally).

First, you output the filename to a text file (length.txt)

   echo %filename%>length.txt

Noticse there is no space between %filename%, '>' and length.txt.

Now, the size (in bytes) of length.txt is simply the length of the filename + linefeed + carriagr return.

You need to get this size and assign it to a variable and at the same time, subtract 2 from it. Like this:

   for %%l in (length.txt) do set /a length=%%~zl-2

%%l would normally return just the filename (length.txt) however, %%~zl returns just it's size in bytes. Remember we need to subtract 2 from this, so we use SET /A to perform an arithmethmetic assignment. The variable %length% will be set to the size of length.txt - 2.

Finally, you can output this variable to a file like so:

   echo %length%>file.txt

So, the file file.txt now contains an integer equal to the length of the filename which was output to the file length.txt earlier.


Example:

This code does a DIR to fetch each filename in your source folder. The FOR-variable (%%a) picks up each filename in turn expanding it to it's full path/filename (%%~dpnxa) and outputing it to the file length.txt. The rest is as explained above. Here goes:


   for /f "tokens=*" %%a in ('dir /a-d /b %source%\*.*') do (
      echo %%~dpnxa>length.txt
      for %%f in (length.txt) do set /a !length!=%%~zf-2
         echo !length!>>file.txt
      )
   )

file.txt will contain a list of integers. I've used '>>' instead of just '>' so as to append each integer to the file. Notice the use of !length! instead of %length% - this is due to variable expansion issues while working with changing variable inside FOR loop.

The only other thing you need to be aware of is the file length.txt which is still lurking on your system so a simple DEL length.txt will sort that out.

Oh, I see billprew has already given a possible solution. Apologies for the double-comment, I pressed something I shouldn't have done and it sent the comment before I had time to finish writing.
Sorry, "set /a !length!=%%~zf-2" is nonsense! I meant....


   for /f "tokens=*" %%a in ('dir /a-d /b %source%\*.*') do (
      echo %%~dpnxa>length.txt
      for %%f in (length.txt) do set /a length=%%~zf-2
         echo !length!   %%a>>file.txt
      )
   )


This outputs both the length and the filename to file.txt.

Oh, and don't forget to preceed the code with:

   setlocal enabledelayedexpansion

in order for !variables! to work.

This is the type of thing I often do with a small subroutine, as shown below.

~bp
@echo off
setlocal EnableDelayedExpansion
setlocal EnableExtensions
 
set FileName=c:\temp\dir1\this is a long file name.txt
call :Length "%FileName%" "FileLength"
echo %FileName%
echo %FileLength%
exit /b
 
:Length
  REM Calculate the length of a passed in string in parm1, 
  REM return length in variable named in parm2
  echo %~1>"%TEMP%\_length_.txt"
  for %%A in ("%TEMP%\_length_.txt") do (
    set /a %~2=%%~zA
    set /a %~2 -= 2
    del "%TEMP%\_length_.txt"
  )
  exit /b

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of t0t0
t0t0
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
t0t0,
I will try your code in a minute.
The code I pasted I got from someone else (dragon-it is his EE name) from another EE post, I did not create it.  I thought that code was sloppy, but i'm not an expert on batch filing.  I may a 'guru' in many other things, but batch file scripting is not one of them.  Your code is much more clearer and I will try that now.

Thanks.
There may be a "cart before the horse" scenario here...    What if there is a path is greater than 259 characters?   If situtation exists, then the script will fail with a "Path too long" error message.  I assume that's what this script is intended to find?  If so, then niether a DOS batch file or a VBscript will do...  you'll need a real honest-to-goodness application to find paths greater than 259.  
BTW: 256 (path) +3 (drive, colon, slash) = 259
There are several good utilities out there...  http://www.pathtoolong.com/
and even some VB.Net source code called PathTooDeep.zip....http://www.emmet-gray.com/AdminTools.htm  
believe it or not, it will work when its more than 259 chars.  I came across a folder that has well over 259 chars in its path, i did get the "Path too long" error but it still printed the path to the file, along with all the other file/folder paths.
graye

I'm aware of the 260-character limit of unc pathnames however, consider this: if the batch file encounters a path whose length exceeds this limit then ask yourself how that path was created in the first place. It goes to follow then, if it exists it can be read.

RIght now no one can access anything in that folder, hence the need for the script.  There is a flaw in Microsoft that will allow users to create folder or file names greater than 260 characters.  The user will not get an error until they go to access that folder or file.
t0t0...   No, it will fail...
This scenario is actually quite common.  Here is how it might happen... you have a network share that has a "mount point" deep in a path, say "D:\Something\SomethingElse\EvenMore".   A user maps that share with a drive letter ("M:" is now equivalent to:  "D:\Something\SomethingElse\EvenMore.  From their perspective, they can create a path that 259 characters long... and all is well.   However, if you were to log onto the server, and look at that same physical directory, then you'd get the Path Too Long error message.
So, it's a matter of perspective... when mapped with a drive letter, you get a shorter overall path... but when viewed without a drive letter, you get a longer overall path.
I've got quite a bit of experience with this phenomena, and have even written a set of replacement File.IO classes for the .Net framework to allow it to traverse directories that are "too long".
t0t0, I ran your code and I get the error that says "specified file cannot be found".  here is the code I have now:

@echo off
setlocal enabledelayedexpansion

REM Enter the source to search in below:
set source="%*"

REM Shows when the search started on screen
echo Started at %time%

set count=0
for /f "tokens=*" %%a in ('dir /ad /b /s "%*"') do (
 set line=%%a
 if not "!line:~205!"=="" (
 set /a count+=1
 echo %%a>length.tmp
 for %%l in (length.tmp) do set /a length=%%~zl-2
   echo !line! !length! >> out_.txt
 )
 )

) else (goto :next)
)
:next
echo Finished at %time%

copy out_.txt "\\ngs-s-2-ops1\c$\scripts\path size\"
pause
exit /b
exit
I will comment a later date... but Paul, my batch file this was taken from was for a different purpose, took a path on a commandline, the sort was at pos 256 and reverse sorted so that only those with chars beyond 260 point got included in the list.  Worked for me at the time and I believe we had discussions at the time and my method was a lot quicker but may or not have issues I don't know.

Not sure what I have done to deserve a batch file puled apart like this when it is a mangled version of a working one I posted...

Have been busy msyelf so not much time to look on EE

Having a bad day?
 
Steve
Oh btw the sort was becausea sort takes a few seconds and means you can stop processing at batch file slowness beyond find the last entry over xx chars...

Steve.... Don't take it to heart. I was digging you as one EE expert would to another. I could have ended the whole comment with a smiley but that would have inferred a non-seriousness to some of the points I made.

It would be the same as if we were about to sit down together for lunch at your work's canteen while engaging in a light chat about something technically programatic and I were to turn to you and say "And you call yourself a programmer!?"... To which you would probably smile and say nothing! (and wait until the opportunity to get one back at me arises).

TrishITGuru

Thankyou for accepting my solution (pity you overlooked some subtle details). Notice the improvement to setting source. BTW, you made no use of %source% in your code above - see how I've implemented it in the FOR loop.

I'm still not sure about the '205' thing... Perhaps you could change this to something closer to 260.

Finally, it might be better to MOVE out_.txt "\\ngs-s-2-ops1\c$\scripts\path size\" rather than copy it otherwise, you'll end up appending lines again to the same file next time you run the code however, to prevent from this happening, you could merely delete the file to start with. Use this:

   DEL out_.txt 2>nul


I've tidied up bits which you left in (from dragon-it's code.... Hmmm...). This should work for you....


@echo off
setlocal enabledelayedexpansion

REM Enter the source to search in below:
if not "%1"=="" (
   set source=%1
) else (
   source="%*"
)

REM Shows when the search started on screen
echo Started at %time%

set count=0
for /f "tokens=*" %%a in ('dir /ad /b /s "%source%"') do (
   set line=%%a
   if not "!line:~205!"=="" (
      set /a count+=1
      echo %%a>length.tmp
      for %%l in (length.tmp) do set /a length=%%~zl-2
      echo !line! !length!>>out_.txt
   )
)

echo Finished at %time%

copy out_.txt "\\ngs-s-2-ops1\c$\scripts\path size\"
pause
exit /b
dragon-it, t0t0's code actually runs 15 mins faster than the one I got from you.
Yours took about 30 mins to run, his takes 15 and I get the same results.
It's bound to run faster and more slicker because if you look at the code closely, you'll notice it was written by a PROPER programmer.

You'll also notice there is no FIND command. No SORT command. No intermediate file. No piping....

Infact, what you will notice immediately is how well structured and clear of clutter the code is - where every single character is carefully crafted into words that make up each line of code - a bit like a painting by Van Gogh where each brush-stroke is deliberate to the point of perfection.

That's right! Perfection! Think of me as..... Van T0t0. Then you'll get the picture!

Hahaha......
No comment.... have been programming since about 1983... this is a free site so we dont always have time to spend days on it and that was a script for a different situation which has been mangled...
Steve... Please relax...

And yes! the word "mangled" spring to mind too... I mean, look at this http://#26081168. What's really going on here?...

I'm sure someone once said (or was it me?) "While there are users, there'll always be user errors!".

Appropriate as it is, here's another one of mine: "Give a butcher a scalpal and you'll still end up with a leg of pork!"
1983 eh?.... So, you're a bit of a late-comer then!... and I thought you had some REAL experience... :)