[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 507
  • Last Modified:

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.
0
TrishITGuru
Asked:
TrishITGuru
  • 10
  • 6
  • 3
  • +3
1 Solution
 
Chris BottomleyCommented:
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
0
 
TrishITGuruAuthor Commented:
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
0
 
Chris BottomleyCommented:
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
0
Configuration Guide and Best Practices

Read the guide to learn how to orchestrate Data ONTAP, create application-consistent backups and enable fast recovery from NetApp storage snapshots. Version 9.5 also contains performance and scalability enhancements to meet the needs of the largest enterprise environments.

 
Bill PrewCommented:
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
0
 
t0t0Commented:
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
0
 
t0t0Commented:
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.

0
 
t0t0Commented:
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.
0
 
t0t0Commented:
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.

0
 
Bill PrewCommented:
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

0
 
t0t0Commented:
TrishITGuru

Please read the entire comment. Copy and paste my code (below - and MUCH clearer) and run it as is: Simple....




Your example code is pretty crap. Here's why:


   @echo off

Okay.


   REM Change to 160 columns wide
   mode 160,5000

Is this REALLY necessary? No. And it screws up your DOS box both during and after running the code.


   REM Save as findlong.cmd or whatever.  
   if "%1"=="" goto :help

Mumbo-jumbo. It's up to you whther you need this.


   setlocal enabledelayedexpansion


   set source=%*

Nice touch!


   echo Started at %time%

Okay for testing purposes otherwise, it can go.


   dir "%source%" /ad /s /b |sort /+206 /r > LongName.txt

Absolutely unnecessary! Firstly, it's piping the output of a recursive DIR command through into a SORT command. Why do we need to sort? And why the /r option? This just gobbles up your time.

Also, notice there are spaces between '/r'. '>' and LongName.txt - that's sloppy programming. That just adds an extra character (a space) to the end of each line.

And why the need to create the file LangName.txt in the first place?

Furthemore, where the hell did the number 206 come from?


   for /f "tokens=*" %%a in (longname.txt) do (
      set line=%%a

What the hell... Why not just do this:

   for /f "tokens=*" %%a in ('dir /ad /b "%*"') do (
      set line=%%a

As you can see, there is NO NEED for the file LangName.txt.


      if not "!line:~205!"=="" (echo !line!) else (goto :next)
   )

This just outputs filename to the screen whose length is 206 or greater. Actually, this does not work properly - remember the extra space added to the end of each line?....


   :next

This is naughty! Jumping to a label outside of the code's scope. Hmmm... we all do it at times however, the speghetti-style use of GOTOs is no different than this style of programming.


   echo.
   echo Finished at %time%

Hmmm.... Junk! Not needed!


   Echo Found no. of files:

"Files"? Shouldn't that be "Folders"? What if the folder in %* doesn't exist or is empty?


   find /v /c "NOT-LIKELY" longname.txt

What the hell is this? Why not just maintain a count inside the body of the FOR-loop used earlier?


   pause

Why?
 

   exit /b


All in told. Not the best style I've come across from an expert in EE but you've made your choice. Oh, and by the way, where is the label :help?


This is how I would have written this program:


   @echo off
   setlocal enabledelayedexpansion

   for /f "tokens=*" %%a in ('dir /ad /b /s "%*"') do (
      set line=%%a
      if not "!line:~205!"=="" echo !line!
   )

   exit /b


This would find ALL the folders whose length is 206 or greater. This is how you would use the batch file named FINDVLFN.BAT (find very  long filenames).


Example 1.    FINDVLFN

Example 2.    FINDVLFN  c:\temp

Example 3.    FINDVLFN >file.log

                    or

                    FINDVLFN c:\temp >file.log


I think that's pretty self-explanatory.


Finally. IF you need a count of the filenames, this can be done easily (due to the clarity and good style of programming) like this:

   @echo off
   setlocal enabledelayedexpansion

   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 !line!
      )
   )

   echo %count% folders found.
   exit /b


Now, to  modify this code to get the lengths of each vary long foldername, you need to do this:

   @echo off
   setlocal enabledelayedexpansion

   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!
         echo !length!
      )
   )

   echo %count% folders found.
   exit /b


You could combine the lines:

   echo !line!
   echo !length!

to just:

   echo !length! !line!


Finally (and I mean it this time) IF you want to find the longest foldername, then the following simple edit will do just that:


   @echo off
   setlocal enabledelayedexpansion

   set count=0
   set longest[size]=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

         if !length! gtr !longest[size]! (
            set longest[size]=!length!
            set longest[name]=%%a
         )

         echo !line!
         echo !length!
      )
   )

   echo %count% folders found.
   echo Longest folder is: %longest[size]% %longest[name]%
   exit /b
0
 
TrishITGuruAuthor Commented:
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.
0
 
grayeCommented:
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  
0
 
TrishITGuruAuthor Commented:
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.
0
 
t0t0Commented:
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.

0
 
TrishITGuruAuthor Commented:
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.
0
 
grayeCommented:
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".
0
 
TrishITGuruAuthor Commented:
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
0
 
Steve KnightIT ConsultancyCommented:
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
0
 
Steve KnightIT ConsultancyCommented:
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...

0
 
t0t0Commented:
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
0
 
TrishITGuruAuthor Commented:
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.
0
 
t0t0Commented:
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......
0
 
Steve KnightIT ConsultancyCommented:
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...
0
 
t0t0Commented:
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!"
0
 
t0t0Commented:
1983 eh?.... So, you're a bit of a late-comer then!... and I thought you had some REAL experience... :)
0

Featured Post

Transaction-level recovery for Oracle database

Veeam Explore for Oracle delivers low RTOs and RPOs with agentless transaction log backup and transaction-level recovery of Oracle databases. You can restore the database to a precise point in time, even to a specific transaction.

  • 10
  • 6
  • 3
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now