*** The old information ***
---------------------------
The solution below is based on the format of DIR /X /A:-D listing.
E.g. one might have
C:\_M>DIR /X /A:-D
Volume in drive C is WHATEVER
Volume Serial Number is E771-A1B3
Directory of C:\_M
27.02.2005 21:44 24 LONGNA~1.TXT LongNameFile.txt
27.02.2005 21:43 16 test.cmd
2 File(s) 40 bytes
0 Dir(s) 51,807,084,544 bytes free
For a long file name the relevant row contains at least five space
delimited items while the other lines only have four. Furthermore,
the folder listing's footer must be dropped.
@echo off & setlocal enableextensions
set lfn_=
for /f "skip=4 tokens=4-5 delims= " %%a in (
'dir /x /a:-d /-c "%~1" ^|findstr /v /b /c:" "') do (
if not [%%b]==[] if /i not [%%a]==[%%b] set lfn_=true)
if [%lfn_%]==[] (
echo No long file names found in folder %1
) ELSE (
echo Long file names found in folder %1)
endlocal & goto :EOF
You may wish to take a look at
dir /?
findstr /?|more
The method can also be used to detect the LFN-status of a single
file:
@echo off & setlocal enableextensions
::
if [%1]==[] (
echo Usage: %~0 [FileName]
goto :EOF)
::
echo %1|findstr "[*?]">nul
if %errorlevel% EQU 0 (
echo %1 contains wildcards, not allowed
goto :EOF)
::
if not exist "%~1" (
echo File %1 not found
goto :EOF)
::
dir /a:d "%~1" 2>&1 |findstr /c:"<DIR>">nul
if %errorlevel% EQU 0 (
echo %1 is a folder
goto :EOF)
::
set lfn_=
for /f "skip=4 tokens=4-5 delims= " %%a in (
'dir /x /a:-d /-c "%~1" ^|findstr /v /b /c:" "') do (
if not [%%b]==[] if /i not [%%a]==[%%b] set lfn_=true)
if [%lfn_%]==[] (
echo %1 is not a long file name
) ELSE (
echo %1 is a long file name)
endlocal & goto :EOF
---------------------------------
*** The added new information ***
---------------------------------
There are other methods. First consider the task of getting the
short format of a filename
@echo off & setlocal enableextensions enabledelayedexpansion
for %%f in ("%~1") do (
set lfn=%%~ff
set sfn=%%~sf
if not exist "!lfn!" (
echo File "!lfn!" not found
) else (
echo !lfn!
echo !sfn!
)
)
endlocal & goto :EOF
The output might be e.g.
C:\_D\TEST>cmdfaq "C:\_M\test 2.txt"
C:\_M\test 2.txt
C:\_M\TEST2~1.TXT
Drawing from the above we have
@echo off & setlocal enableextensions enabledelayedexpansion
::
if "%~1"=="" (
echo Usage %~0 [FolderName]
goto :EOF
)
::
if not exist "%~1\" (
echo Folder %~1\ not found
goto :EOF
)
::
set lfnFound=
for %%f in ("%~1\*.*") do (
set lfn=%%~ff
set sfn=%%~sf
if /i not "!lfn!"=="!sfn!" set lfnFound=true
)
::
if defined lfnFound (
echo Long file names found in folder "%~1"
) ELSE (
echo No long file names found in folder "%~1")
endlocal & goto :EOF
The output might be e.g.
C:\_D\TEST>cmdfaq C:\_D\TEST
Long file names found in folder "C:\_D\TEST"
References/Comments:
http://groups.google.com/group/alt.msdos.batch/msg/f6adf6c67d47359d
All the best, Timo
--
Prof. Timo Salmi ftp & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:t...@uwasa.fi <http://www.uwasa.fi/~ts/> ; FIN-65101, Finland
Useful script files and tricks ftp://garbo.uwasa.fi/pc/link/tscmd.zip
@echo off
for %%? in (%*) do call :Check %%?
goto :eof
:Check
if not exist "%~f1" (echo.
echo The folder '%~nx1' does not exist.
goto :eof)
if not exist "%~f1\" (echo.
echo '%~nx1' is not a folder.
goto :eof)
for /f %%? in ('dir /a /l "%~f1"^|find "File(s)"') do if %%? equ 0
(echo.
echo The folder '%~nx1' is empty.
goto :eof)
set found=false
for /f %%? in ('dir /a:-d /b "%~f1"^|find " "') do set found=true
if "%found%"=="true" (echo.
echo The folder '%~nx1' contains files with long names.) else (echo.
echo The folder '%~nx1' does not contain files with long names.)
goto :eof
Does it cater for a long filename that has no spaces etc?
> If the filename has spaces, it is a long name, as long as the filename
> does not contain spaces, it is not a long name.
Not where I grew up. :)
C:\junkdir>dir /a-d | find "/"
02/22/2006 11:37 AM 0
This_is_a_long_file_name_but_it_does_not_contain_any_spaces.txt
--
Phil Robyn
University of California, Berkeley
C:\junkdir>dir /x /a-d | find "/"
02/22/2006 12:52 PM 0 THIS_I~1.TXT
@echo off
if "%~1"=="" (echo.
echo %~n0 ^<Folders^>
goto :eof)
for %%? in (%*) do call :Check %%?
goto :eof
:Check
if not exist "%~f1" (echo.
echo The folder '%~nx1' does not exist.
goto :eof)
if not exist "%~f1\" (echo.
echo '%~nx1' is not a folder.
goto :eof)
for /f %%? in ('dir /a /l "%~f1"^|find "File(s)"') do if %%? equ 0
(echo.
echo The folder '%~nx1' is empty.
goto :eof)
set found=false
call :Check2 %~s1
if "%found%"=="true" (echo.
echo The folder '%~nx1' contains files with long names.) else if
"%found%"=="false" (echo.
echo The folder '%~nx1' does not contain files with long names.)
goto :eof
:Check2
for %%? in ("%1\*") do (if /i not "%%~f?"=="%%~s?" (set found=true
goto :eof))
goto :eof
Wrong. Long filenames include filenames with spaces, more than one dot,
any portion between dots exceeding 8 characters or the portion after
the last dot exceeding 3 characters. Long filenames with no spaces can
still cause problems for programs that expect only 8-dot-3 filenames.
*YOU* may have no problems with filenames without spaces. Don't assume
the same for everyone else.
But all you need is something like
@REM -- begin batch file --
@echo off & setlocal
:: minimal error checking
if not "%~1" == "" if exist "%~1\." goto CONTINUE
echo Usage: %0 path
goto :EOF
:CONTINUE
set __bs=
for %%f in (%~1\*) do if not "%%~ff" == "%%~sf" set __bs=%%f
if "%__bs%" == "" (
echo No long filenames found in %1
) else (
echo Some long filenames found in %1, e.g., %__bs%
)
@REM -- end batch file --
>If the filename has spaces, it is a long name, as long as the filename
>does not contain spaces, it is not a long name.
AFAIK every version of DOS allowed spaces in filenames. The default
command shell didn't let you, but they certainly could be created with
BASIC and other programs, like XTREE.
IMO a long filename is one which exceeds 8.3
--
Michael Bednarek http://mbednarek.com/ "POST NO BILLS"
No, a long file name is what Windows considers a "long file name".
The correct definition is embedded in the scripts I posted. We may
try to state the definition verbally (see Harlan's good wording),
but it is the OS that decides what is a long file name and what not.
The "long file name" term is slightly inaccurate, since indeed file
names shorter than 8+3 can be long files names in the OS's eyes. And
that is what counts.
>Michael Bednarek wrote:
>> IMO a long filename is one which exceeds 8.3
>
>No, a long file name is what Windows considers a "long file name".
>The correct definition is embedded in the scripts I posted. We may
>try to state the definition verbally (see Harlan's good wording),
>but it is the OS that decides what is a long file name and what not.
>The "long file name" term is slightly inaccurate, since indeed file
>names shorter than 8+3 can be long files names in the OS's eyes. And
>that is what counts.
You're right. Harlan's wording and your code seem indeed to reflect what
NT/NTFS considers a long filename. I mislead myself by remembering that
DOS allowed spaces in filenames, and then assuming that
"DOS filenames" = "NT Short Filenames" - which is not true.
Did you have an opportunity to run your code on a system where the
generation of short filenames has been switched off
(NtfsDisable8dot3NameCreation=1)?
Just for the sake of (academic) completeness: there's also the setting
Win31FileSystem=1 which apparently will force NT to use short filenames.
By itself, this is already surely a recipe for disaster, but I wonder
what happens if both of these are enabled? No filenames at all?
Lastly, just for fun and not proving anything, consider this:
DIR /X
23/02/06 19:27 3 FU.BAR test 2.txt
First, change the IF command and remove the dot here: if exist "%~1\."
goto CONTINUE
Also, change the IF command and add the /I switch here: if not "%%~ff"
== "%%~sf" set __bs=%%f
My script supports multiple paths, and it checks three things:
1. If the object exists.
2. If the object does exist, it checks if it's a file or a folder.
(yours is broken here)
3. If the object is a folder, it checks if it's empty from files.
Now, I improved it:
@echo off
setlocal enabledelayedexpansion
if "%~1"=="" (echo.
echo %~n0 ^<Folders^>
goto :eof)
for %%? in (%*) do call :Check %%?
goto :eof
:Check
if not exist "%~f1" (echo.
echo The folder '%~nx1' does not exist.
goto :eof)
if not exist "%~f1\" (echo.
echo '%~nx1' is not a folder.
goto :eof)
for /f %%? in ('dir /a /l "%~f1"^|find "File(s)"') do if %%? equ 0
(echo.
echo The folder '%~nx1' is empty.
goto :eof)
set x=0
for %%? in (%~s1\*) do (if /i not "%%~f?"=="%%~s?" (set /a x+=1
set file!x!=%%~nx?))
if %x% geq 1 (echo.
echo The folder '%~nx1' contains files with long names:
echo.
for /l %%? in (1 1 %x%) do call echo %%file%%?%%) else (echo.
echo The folder '%~nx1' does not contain files with long names.)
goto :eof
> On Thu, 23 Feb 2006 08:15:00 +0200, Timo Salmi wrote
>> .. a long file name is what Windows considers a "long file
>> name".
> Did you have an opportunity to run your code on a system where the
> generation of short filenames has been switched off
> (NtfsDisable8dot3NameCreation=1)?
No, I did not. Furthermore, the level of sophistication goes beyond
my FAQ and also myself. However, it is a good and interesting
consideration for the discussion in the newsgroup.
@echo off
if "%~1"=="" (echo.
echo %~n0 ^<Folders^>
goto :eof)
for %%? in (%*) do call :Check %%?
goto :eof
:Check
if not exist "%~f1" (echo.
echo The folder '%~nx1' does not exist.
goto :eof)
if not exist "%~f1\" (echo.
echo '%~nx1' is not a folder.
goto :eof)
for /f %%? in ('dir /a /l %~s1^|find "File(s)"') do if %%? equ 0 (echo.
echo The folder '%~nx1' is empty.
goto :eof)
set x=0
for /f "tokens=5*" %%a in ('dir /a:-d /x %~s1^|findstr /b /v /c:" "')
do if not "%%b"=="" if /i not "%%a"=="%%b" (set /a x+=1
set file!x!=%%b)
if %x% geq 1 (echo.
echo The folder '%~nx1' contains files with long names:
echo.
for /l %%? in (1 1 %x%) do call echo %%file%%?%%) else (echo.
> I noticed that my script doesn't find hidden files, I guess the shorter
> solution is to use DIR and FINDSTR:
It looks feasible, but are you aware of the short filename bug in cmd?
The bug strikes when the folder or filename is short and has spaces (or
other long filename components?) then the %~sA style of construct returns
the short name but includes a trailing portion of the long filename after
it.
IE:
If the long name is "c:\the file.txt"
cmd might return "C:\THEFILE~1.TXT ile.txt"
That's just a crude example and I think the bug is erratic.
Another academic tangent.
You're right that MS-DOS allowed spaces in filenames between graphic
characters. I wonder if there could ever be trouble arising from 16-bit
programs recognizing filenames with embedded spaces with 8 or fewer chars in
the base filename and 3 or fewer chars in the extension when they call the
underlying WinNT subsystems. I'll admit my ignorance on this point: when
16-bit programs make INT 21H OS calls involving filenames, does the NT
subsystem that actually processes the requests try to match up the supplied
filename against both short and long NTFS or FAT32 filenames?
They were not allowed in DOS; read the books.
They were, however, possible, by means such as you indicate.
They are, in DOS, like knocking off an on-duty policeman's headgear :-
definitely not allowed, fairly easily achieved, and with the likelihood
of adverse consequences unless adequate care is taken.
ISTM desirable that any FAQ item on file name classification should
describe, in words, its approach to making the decision, and what
definition of LFN that may implement. AFAICS, Timo's method relies on
DIR sometimes providing only one file name and sometimes providing two
(in which case, as Win9x has LFNs but does not do that, a downwards
compatibility warning might be on order).
BTW, is it known whether NTFS stores SFNs at
all, or whether it generates them as required?
Another definition might be whether the name would be stored without
loss in a single 8.3 entry; that would allow characters such as Pound
and Half.
Another definition might be whether the name obeys the rules in the DOS
manuals - within 8.3 and using a limited character set.
Different discriminations may be appropriate for different purposes :
for example, the "spaces" criterion governs the need for using quotes.
--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk DOS 3.3, 6.20; Win98. ©
Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links.
PAS EXE TXT ZIP via <URL:http://www.merlyn.demon.co.uk/programs/00index.htm>
My DOS <URL:http://www.merlyn.demon.co.uk/batfiles.htm> - also batprogs.htm.
Semantics. OSs have much more ability to enforce their prohibitions than
society has to enforce laws. In the context of OSs anything possible is ipso
facto allowed. Discouraged and/or difficult aren't the same as disallowed.
Apter metaphor would be butt scratching. Not illegal, just frowned upon.
Spaces as the first char in a filename indicated that the file had been
deleted, and spaces after the last nonspace char in either basename or
extension were ignored. So space as first char in base filename was the only
place in which they weren't allowed.
As for adverse consequences? Some software, e.g., Lotus 123, choked on files
containing embedded spaces, but that's because such programs provided
unnecessary extra-OS filename validity checking. MS-DOS itself and much
other software, e.g., PC-Write and BASICA, had no problems with such
filenames.
>Another definition might be whether the name obeys the rules in the DOS
>manuals - within 8.3 and using a limited character set.
...
If you're taking Microsoft manuals as gospel truth, that would explain a
lot.
Anyway, the only MS manual I have is the 'Microsoft MS-DOS Operating System
Programmer's Reference Manual', last copyright year 1984, document number
8411-310-02, which states on page 3-3:
"All directory entries are 32 bytes in length, and are in the following
format (note that byte offsets are in hexadecimal):
0-7 Filename. Eight characters, left aligned and padded, if necessary, with
blanks. The first byte of this field indicates the file status as
follows:
00H The directory entry has never been used. This is used to limit the
length of the directory searches, for performance reasons.
05H Indicates that the first character of the filename actually has an
E5H character.
2EH The entry is for a directory. If the second byte is also 2EH, then
the cluster field contains the cluster number of this directory's
parent directory (0000H if the parent directory is the root
directory). [...]
E5H The file was used, but it has been erased.
Any other character is the first character of a filename."
Implying that filenames could contain control characters, colons, slashes,
backslashes and spaces. Any character except 00H, 2EH and E5H. That's
clearly wrong. Maybe my own experience with the Office manuals has jaded me,
but I don't expect even a nod towards a passing aquaintance with perfection
or completeness from Microsoft manuals.
OK, that's a bug.
>Also, change the IF command and add the /I switch here: if not "%%~ff"
>== "%%~sf" set __bs=%%f
That doesn't seem to be necessary. I've tested all the case permutations for
4 letter filenames, and there were none for which %%~ff and %%~sf differed.
Can you provide any examples of files without embedded spaces for which long
and short filenames differ only by letter case?
>My script supports multiple paths, and it checks three things:
Begging the question whether that's useful or not. If LFN testing would be
used as part of a larger batch file, then the multiple argument loop would
be more of a hindrance than a help.
But why reinvent the wheel in each batch file in which multiple argument
processing would be useful? Why not use a common batch file to call other
batch files?
@REM -- begin mc.bat --
@echo off & setlocal
set __cmd=%1
:LOOP
shift
if "%1" == "" goto END
for %%f in (%1) do call %__cmd% %%f
goto LOOP
:END
@REM -- end mc.bat --
Then use it to call other batch files (or programs) that don't need to (or
can't) include argument looping. Just an alternative.
>1. If the object exists.
>2. If the object does exist, it checks if it's a file or a folder.
>(yours is broken here)
Removing the dot in the first IF line handles this.
>3. If the object is a folder, it checks if it's empty from files.
Wouldn't empty folders have no long filenames in them?
>Now, I improved it:
>
> @echo off
> setlocal enabledelayedexpansion
> if "%~1"=="" (echo.
> echo %~n0 ^<Folders^>
> goto :eof)
> for %%? in (%*) do call :Check %%?
> goto :eof
> :Check
> if not exist "%~f1" (echo.
> echo The folder '%~nx1' does not exist.
> goto :eof)
> if not exist "%~f1\" (echo.
> echo '%~nx1' is not a folder.
> goto :eof)
> for /f %%? in ('dir /a /l "%~f1"^|find "File(s)"') do if %%? equ 0
> (echo.
> echo The folder '%~nx1' is empty.
> goto :eof)
Arguably more elegant to use the Unix-y ||.
dir /a /b "%~f1" | findstr /r ".*" > nul || ( echo/ & ...
> set x=0
> for %%? in (%~s1\*) do (if /i not "%%~f?"=="%%~s?" (set /a x+=1
> set file!x!=%%~nx?))
> if %x% geq 1 (echo.
> echo The folder '%~nx1' contains files with long names:
> echo.
> for /l %%? in (1 1 %x%) do call echo %%file%%?%%) else (echo.
> echo The folder '%~nx1' does not contain files with long names.)
> goto :eof
OK, you list all such files stored as environment variables. If there were
many long filenames, this could become noticeably slow. Better to list them
after the fact, deleting the 'set file!x!=%%~nx?' command, and replacing the
'for /l %%? in (1 1 %x%) do call echo %%file%%?%%' command with
for %%? in (%~1\*) do if not "%%~f?" == "%%~s?" echo %%~f?
This may seem redundant going through the directory again, but in terms of
execution time it beats repeatedly dereferencing the environment table.
>"Michael Bednarek" wrote...
I'm pretty sure it does. Look at this:
$ DIR te*
23/02/06 19:27 3 test 2.txt
$ DIR fu*
23/02/06 19:27 3 test 2.txt
$ DIR /X te*
23/02/06 19:27 3 FU.BAR test 2.txt
$ DIR /X fu*
23/02/06 19:27 3 FU.BAR test 2.txt
Incidentally, this behaviour, which can be disconcerting, can be turned
off in 4NT/4DOS with
OPTION //Win32SFNSearch=No
(Win95SFNSearch in 4DOS)
That is necessary, at least on my system, %%~sf change some of the
letters to capital letters.
> >My script supports multiple paths, and it checks three things:
>
> Begging the question whether that's useful or not. If LFN testing would be
> used as part of a larger batch file, then the multiple argument loop would
> be more of a hindrance than a help.
Of course that's useful.
We need to check if the given argument is a file or a folder, also we
need to check if it's not empty from files.
> But why reinvent the wheel in each batch file in which multiple argument
> processing would be useful? Why not use a common batch file to call other
> batch files?
>
> @REM -- begin mc.bat --
> @echo off & setlocal
> set __cmd=%1
> :LOOP
> shift
> if "%1" == "" goto END
> for %%f in (%1) do call %__cmd% %%f
> goto LOOP
> :END
> @REM -- end mc.bat --
> Then use it to call other batch files (or programs) that don't need to (or
> can't) include argument looping. Just an alternative.
Very bad idea.
Why not just to use a FOR loop to handle all the parameters the user
entered?
> >1. If the object exists.
> >2. If the object does exist, it checks if it's a file or a folder.
> >(yours is broken here)
>
> Removing the dot in the first IF line handles this.
>
> >3. If the object is a folder, it checks if it's empty from files.
>
> Wouldn't empty folders have no long filenames in them?
We need to check if the folder is not empty from files first, then
we'll see if it has any long names in it.
Another bad idea.
First I need to see if the 'X' variable equals or greater than 1, then
I can print that the folder has long names in it, otherwise, we need to
print that the folder does not contain long names.
Here is the current code:
@echo off
if "%~1"=="" (echo.
echo %~n0 ^<Folders^>
goto :eof)
for %%? in (%*) do call :Check %%?
goto :eof
:Check
if not exist "%~f1" (echo.
echo The folder '%~nx1' does not exist.
goto :eof)
if not exist "%~f1\" (echo.
echo '%~nx1' is not a folder.
goto :eof)
for /f %%? in ('dir /a /l %~s1^|find "File(s)"') do if %%? equ 0 (echo.
echo The folder '%~nx1' is empty.
goto :eof)
set x=0
for /f "tokens=5*" %%a in ('dir /a:-d /x %~s1^|findstr /b /v /c:" "')
do if not "%%b"=="" if /i not "%%a"=="%%b" (set /a x+=1
set file!x!=%%b)
if %x% geq 1 (echo.
echo The folder '%~nx1' contains files with long names:
echo.
for /l %%? in (1 1 %x%) do call echo %%file%%?%%) else (echo.
echo The folder '%~nx1' does not contain files with long names.)
goto :eof
As you can see, I changed the technique to DIR and FINDSTR to it can
handle hidden files.
There is another solution to handle hidden files, but it's
unnecessarily longer.
It may be hard to tell, but I meant my question sincerely: what's an
example of a filename that could have been an 8-dot-3 filename ignoring
letter case for which NT or successors gives different long and short
filenames? I'd like to test them on my own system because I'd like to
know whether this could vary with language settings.
>>But why reinvent the wheel in each batch file in which multiple argument
>>processing would be useful? Why not use a common batch file to call other
>>batch files?
...
>Very bad idea.
>Why not just to use a FOR loop to handle all the parameters the user
>entered?
...
Because then every batch file that could be passed multiple independent
arguments would need such a for loop. This is a library vs in-line
trade-off, and your 'good' idea seems bad to me while my idea seems bad
to you.
>>>3. If the object is a folder, it checks if it's empty from files.
>>
>> Wouldn't empty folders have no long filenames in them?
>
>We need to check if the folder is not empty from files first, then
>we'll see if it has any long names in it.
...
Why necessary? If a set is empty, it can have no members of any type.
Is the task *both* testing whether the directory contains any files and
if so whether some have long filenames or is it just testing whether
the directory has some files with long filenames?
>>OK, you list all such files stored as environment variables. If there were
>>many long filenames, this could become noticeably slow. Better to list them
>>after the fact, deleting the 'set file!x!=%%~nx?' command, and replacing the
>>'for /l %%? in (1 1 %x%) do call echo %%file%%?%%' command with
>>
>>for %%? in (%~1\*) do if not "%%~f?" == "%%~s?" echo %%~f?
>>
>>This may seem redundant going through the directory again, but in terms of
>>execution time it beats repeatedly dereferencing the environment table.
>
>Another bad idea.
>First I need to see if the 'X' variable equals or greater than 1, then
>I can print that the folder has long names in it, otherwise, we need to
>print that the folder does not contain long names.
You misunderstand my point. I was only addressing storing long
filenames in environment variables and dereferencing them later. In
directories with many long filenames, you'll notice the processing time
involved in creating and dereferencing those environment variables.
Using the simple loop I proposed would execute faster. Just replacing
one for loop with another.
>Here is the current code:
...
>for /f "tokens=5*" %%a in ('dir /a:-d /x %~s1^|findstr /b /v /c:" "')
>do if not "%%b"=="" if /i not "%%a"=="%%b" (set /a x+=1
>set file!x!=%%b)
...
>As you can see, I changed the technique to DIR and FINDSTR to it can
>handle hidden files.
It's becoming obvious this would be more efficient using findstr with
multiple regular expressions. Something like
@echo off
rem whatever error checking and initialization you want here
(
dir /a-d /b %1\"* *"
dir /a-d /b %1 | findstr /v /c:" " | findstr /r "^[.] [.]..*[.]
[.][^.][^.][^.][^.] [^.][^.][^.][^.][^.][^.][^.][^.][^.]"
) > %0.tmp 2> nul
findstr /r ".*" %0.tmp > nul
if errorlevel 1 (
echo No long filenames found in %1
) else (
echo Some long filenames found in %1:
type %0.tmp
)
del %0.tmp
Note: there should be 2 leading spaces on each line. If there aren't,
then the line has wrapped and should be appended to the end of the
preceding line. Note also that two dir commands are needed since
findstr doesn't seem to like the regexp "[ ]".
I don't undrestand what you said here.
> >>>3. If the object is a folder, it checks if it's empty from files.
> >>
> >> Wouldn't empty folders have no long filenames in them?
> >
> >We need to check if the folder is not empty from files first, then
> >we'll see if it has any long names in it.
> ...
>
> Why necessary? If a set is empty, it can have no members of any type.
> Is the task *both* testing whether the directory contains any files and
> if so whether some have long filenames or is it just testing whether
> the directory has some files with long filenames?
I think you don't understand.
The FOR loop just checks if the folder is empty from files, if so,
what's the point to continue the process?
> >>OK, you list all such files stored as environment variables. If there were
> >>many long filenames, this could become noticeably slow. Better to list them
> >>after the fact, deleting the 'set file!x!=%%~nx?' command, and replacing the
> >>'for /l %%? in (1 1 %x%) do call echo %%file%%?%%' command with
> >>
> >>for %%? in (%~1\*) do if not "%%~f?" == "%%~s?" echo %%~f?
> >>
> >>This may seem redundant going through the directory again, but in terms of
> >>execution time it beats repeatedly dereferencing the environment table.
> >
> >Another bad idea.
> >First I need to see if the 'X' variable equals or greater than 1, then
> >I can print that the folder has long names in it, otherwise, we need to
> >print that the folder does not contain long names.
>
> You misunderstand my point. I was only addressing storing long
> filenames in environment variables and dereferencing them later. In
> directories with many long filenames, you'll notice the processing time
> involved in creating and dereferencing those environment variables.
> Using the simple loop I proposed would execute faster. Just replacing
> one for loop with another.
No, then it will show the files first, I want to print a message first.
I don't understand what you did here too.
It's really hard for me to understand you so you'll have to excuse me.
I use something like the mc.bat that I posted a few responses ago. It
also works with .COM and .EXE files that take single arguments and
often can't be modified, so I could use command lines like
mc my.exe a b c d e f g
and mc.bat would run my.exe 7 times with each subsequent argument
separately. I use the same batch file to call other batch files
repeatedly with the separate subsequent arguments passed to mc.bat. I
don't need to add for loops to every batch file to process multiple
independent arguments, so most of my batch files are simpler, so more
easily maintained.
You prefer in-line for loops in each batch file to process multiple
arguments. That makes sense to you - your batch files work stand alone.
I find that wasteful. Instead, I use a common driver batch file for
looping through arguments and calling other batch files or programs
with each argument after the batch file or program name. That makes
sense to me - simplification of other batch files, utility with .COM
and .EXE files too, and reduced batch files sizes. I can live with the
fact that my other batch files may not be stand alone in terms of
handling multiple arguments. It's subjective, which means it's just
counter to your preferences.
>>Why necessary? If a set is empty, it can have no members of any type.
>>Is the task *both* testing whether the directory contains any files and
>>if so whether some have long filenames or is it just testing whether
>>the directory has some files with long filenames?
>
>I think you don't understand.
>The FOR loop just checks if the folder is empty from files, if so,
>what's the point to continue the process?
Nope. I understand that you're performing the check for empty
directories in order to avoid looking for files with long filenames in
them. However, without that check, the for loop checking for long
filenames would run VERY QUICKLY for empty directories and would report
that no long filenames were found. We have a difference of opinion
about the value of distinguishing empty directories from nonempty
directories containing no long filenames.
> > >>OK, you list all such files stored as environment variables. If there were
> > >>many long filenames, this could become noticeably slow. Better to list them
> > >>after the fact, deleting the 'set file!x!=%%~nx?' command, and replacing the
> > >>'for /l %%? in (1 1 %x%) do call echo %%file%%?%%' command with
> > >>
> > >>for %%? in (%~1\*) do if not "%%~f?" == "%%~s?" echo %%~f?
> > >>
> > >>This may seem redundant going through the directory again, but in terms of
> > >>execution time it beats repeatedly dereferencing the environment table.
> > >
> > >Another bad idea.
> > >First I need to see if the 'X' variable equals or greater than 1, then
> > >I can print that the folder has long names in it, otherwise, we need to
> > >print that the folder does not contain long names.
> >
> > You misunderstand my point. I was only addressing storing long
> > filenames in environment variables and dereferencing them later. In
> > directories with many long filenames, you'll notice the processing time
> > involved in creating and dereferencing those environment variables.
> > Using the simple loop I proposed would execute faster. Just replacing
> > one for loop with another.
>
>No, then it will show the files first, I want to print a message first.
...
I suppose it doesn't occur to you to put the message first then the for
loop? I guess I need to be explicit. Replace these lines from your
previous batch file
set x=0
for %%? in (%~s1\*) do (if /i not "%%~f?"=="%%~s?" (set /a x+=1
set file!x!=%%~nx?))
if %x% geq 1 (echo.
echo The folder '%~nx1' contains files with long names:
echo.
for /l %%? in (1 1 %x%) do call echo %%file%%?%%) else (echo.
echo The folder '%~nx1' does not contain files with long names.)
with
echo.
set x=0
for %%? in (%1\*) do if /i not "%%~f?"=="%%~s?" set x=1
if %x% == 1 (
echo The folder '%~nx1' contains files with long names:
echo.
for %%? in (%1\*) do if /i not "%%~f?" == "%%~s?" echo %%~n?
) else (
echo The folder "%~1" does not contain files with long names.
)
or if you prefer
echo.
set x=echo
for %%? in (%1\*) do if /i not "%%~f?"=="%%~s?" (
call %%x%% The folder '%~nx1' contains files with long names:
set x=rem
echo %%~n?
)
if %x% == 0 echo The folder "%~1" does not contain files with long
names.
>>It's becoming obvious this would be more efficient using findstr with
>>multiple regular expressions. Something like
>>
>> @echo off
>> rem whatever error checking and initialization you want here
>> (
>> dir /a-d /b %1\"* *"
>> dir /a-d /b %1 | findstr /v /c:" " | findstr /r "^[.] [.]..*[.]
>>[.][^.][^.][^.][^.] [^.][^.][^.][^.][^.][^.][^.][^.][^.]"
>> ) > %0.tmp 2> nul
>> findstr /r ".*" %0.tmp > nul
>> if errorlevel 1 (
>> echo No long filenames found in %1
>> ) else (
>> echo Some long filenames found in %1:
>> type %0.tmp
>> )
>> del %0.tmp
>>
>>Note: there should be 2 leading spaces on each line. If there aren't,
>>then the line has wrapped and should be appended to the end of the
>>preceding line. Note also that two dir commands are needed since
>>findstr doesn't seem to like the regexp "[ ]".
>
>I don't understand what you did here too.
>
>It's really hard for me to understand you so you'll have to excuse me.
OK, so you don't understand using findstr with regular expressions.
What else don't you understand? Perhaps try creating the batch file
above and try running it with the command lines
batchfile %windir%\temp
and
batchfile C:\
Maybe that'd make it clearer what it does. Hint: the command
findstr /r ".*" filename > nul
is a means of testing whether a file contains anything or is zero
bytes. It sets errorlevel nonzero if filename is zero bytes because it
didn't find any matches to the regular expression ".*", which means any
characters.
@echo off
if "%~1"=="" (echo.
echo %~n0 ^<Folders^>
goto :eof)
for %%? in (%*) do call :Check %%?
goto :eof
:Check
if not exist "%~f1" (echo.
echo The folder '%~nx1' does not exist.
goto :eof)
if not exist "%~f1\" (echo.
echo '%~nx1' is not a folder.
goto :eof)
set x=0
set cmd=echo
for /f "tokens=5*" %%a in ('dir /a:-d /x %~s1 2^>nul^|findstr /v /b
/c:" "') do if not "%%b"=="" if /i not "%%a"=="%%b" (set /a x+=1
call %%cmd%%.
call %%cmd%%.The folder '%~nx1' contains file(s^) with long names:
call %%cmd%%.
set cmd=rem
call echo %%x%%. %%b)
if %x% equ 0 (echo.) & echo The folder '%~nx1' does not contain files
with long names.
goto :eof
>Spaces as the first char in a filename indicated that the file had been
>deleted,
That's enough to prove your ignorance. Deleted files have Hex E5
instead of the original first character; that's Dec 229, or sigma in a
common character set.
>>Another definition might be whether the name obeys the rules in the DOS
>>manuals - within 8.3 and using a limited character set.
>...
>
>If you're taking Microsoft manuals as gospel truth, that would explain a
>lot.
Well, it's an MS OS, and one should always allow for the possibility of
the manual being right.
By complying with the written definition, one has some assurance that
one's code will not break in later releases. That which is not
guaranteed to work is not thereby guaranteed not to work; testing gives
results applying only to the tested system. We are not in Merlyn's
myrmecarium.
>Anyway, the only MS manual I have is the 'Microsoft MS-DOS Operating System
>Programmer's Reference Manual', last copyright year 1984, document number
>8411-310-02, which states on page 3-3:
>
>"All directory entries are 32 bytes in length, and are in the following
>format (note that byte offsets are in hexadecimal):
>
>0-7 Filename. Eight characters, left aligned and padded, if necessary, with
> blanks. The first byte of this field indicates the file status as
>follows:
>
> 00H The directory entry has never been used. This is used to limit the
> length of the directory searches, for performance reasons.
>
> 05H Indicates that the first character of the filename actually has an
> E5H character.
>
> 2EH The entry is for a directory. If the second byte is also 2EH, then
> the cluster field contains the cluster number of this directory's
> parent directory (0000H if the parent directory is the root
> directory). [...]
Not well written; one dot is for *the*, not *a*, directory; and two for
the parent.
>
> E5H The file was used, but it has been erased.
>
> Any other character is the first character of a filename."
>
>Implying that filenames could contain control characters, colons, slashes,
>backslashes and spaces.
No; since the trailing spaces are explicitly padding, that says that
they do not count as part of the name.
That section indicates that other characters, if present, would be
treated as part of the name; but does not legitimise their use.
The DOS 6 manual that I have explicitly lists A-Z 0-9 _ ^ $ ~ ! # % &
- { } @ ` ' ( ) as the only acceptable characters, and explicitly bars
spaces, commas, backslashes, and periods other than the 8.3 one.
Memory tells me that older manuals say much the same.
My Win98 HD contains one file
SFN 3½FLOP~1.LNK
LFN 3½ Floppy (A).lnk
so MS seemingly allows Windows to break DOS rules.
One wonders whether 3½.BAT would count as a LFN.
For someone who regularly bitches about wasting bandwidth, isn't your
response header a wee bit excessive?
>Harlan Grove <hrl...@aol.com> posted :
>
>>Spaces as the first char in a filename indicated that the file had been
>>deleted,
>
>That's enough to prove your ignorance. Deleted files have Hex E5
>instead of the original first character; that's Dec 229, or sigma in a
>common character set.
OK, my statement was wrong in detail. I don't have a Win16 or Windows
95 machine with which to test, but I recall that it was possible to use
DEBUG or Norton Utilities to set the first character to ASCII space (32
decimal or 20 hexadecimal) and the OS would treat such files as if they
had been deleted.
>>>Another definition might be whether the name obeys the rules in the DOS
>>>manuals - within 8.3 and using a limited character set.
>>...
>>
>>If you're taking Microsoft manuals as gospel truth, that would explain a
>>lot.
>
>Well, it's an MS OS, and one should always allow for the possibility of
>the manual being right.
Experience, at least with other Microsoft documentation, shows that
allowing for the possibility of error is the wiser course.
>By complying with the written definition, one has some assurance that
>one's code will not break in later releases. That which is not
>guaranteed to work is not thereby guaranteed not to work; testing gives
>results applying only to the tested system. We are not in Merlyn's
>myrmecarium.
...
Perhaps. Name any version of MS-DOS or PC-DOS or Windows in which the
OS can't handle files on FAT12 or FAT16 disks which include embedded
spaces, i.e., spaces *between* graphic characters. And various books
presumably sanctioned by Microsoft have mentioned this feature, e.g.,
'The Peter Norton Programmer's Guide to the IBM PC', ISBN 0-914845-46-2
(published by Microsoft Press) which mentions this on page 114. Take
it however you please that I'll put more faith in the utility and
accuracy of a 20+ year-old book than in what you may have to
contribute.
>> Any other character is the first character of a filename."
>>
>>Implying that filenames could contain control characters, colons, slashes,
>>backslashes and spaces.
>
>No; since the trailing spaces are explicitly padding, that says that
>they do not count as part of the name.
Begging the question how space as first character in the filename would
be handled.
>That section indicates that other characters, if present, would be
>treated as part of the name; but does not legitimise their use.
Here we have the old problem of deciding whether silence on the subject
of validity implies validity or invalidity. Since the manual I cited
doesn't mention which characters would be valid, where does that leave
us? Perhaps using empiricism and using what seems to work?
>The DOS 6 manual that I have explicitly lists A-Z 0-9 _ ^ $ ~ ! # % &
>- { } @ ` ' ( ) as the only acceptable characters, and explicitly bars
>spaces, commas, backslashes, and periods other than the 8.3 one.
Yup, and the DOS 5 manual (all I have) says about the same thing. It
also mentions using extended characters (decimal codes 128 through
255), as long as you use code page 850. This would imply that one
shouldn't be able to use square brackets, [ ], in filenames. Name any
Microsoft OS that won't accept square brackets in filenames, then
consider how much more of a pain filenames with parentheses are than
filenames with square brackets, and if you need help, consider the file
named ) appearing in the iteration list of a COMMAND.COM for loop.
>My Win98 HD contains one file
> SFN 3½FLOP~1.LNK
> LFN 3½ Floppy (A).lnk
>so MS seemingly allows Windows to break DOS rules.
If one doesn't read the added bit about extended characters or has no
idea what they'd be (since at least the DOS 5 manual fails to define
the term before using it), then one might conclude this.