if exist *.* fails

February 8, 2020 at 05:41:15
Specs: Win 10, 8GB
I'm sure I have come across this issue before, but I'd like to know WHY this is failing. There is no files, but there is also no directory present. Still ..

This is the issue: if you use

if exist *.*

or

if exist *

the CMD interpreter returns true, if the directory is empty (and thus, no files).

Example:

C:\> cd \temp

C:\Temp> mkdir mytest

C:\Temp> cd mytest

C:\Temp\mytest> dir

Volume in drive C is something
Volume Serial Number is XXXX-1111

Directory of C:\Temp\mytest

08/02/2020 14:28 <DIR> .
08/02/2020 14:28 <DIR> ..
0 File(s) 0 bytes
2 Dir(s) 108.083.978.240 bytes free

C:\Temp\mytest> if exist *.* echo Files!
Files!

C:\Temp\mytest> if exist * echo Files!
Files!

C:\Temp\mytest> if exist *.txt echo Files!

C:\Temp\mytest> dir *.* /b

C:\Temp\mytest> dir * /b

C:\Temp\mytest> dir *.txt /b
File Not Found

C:\Temp\mytest>


See More: if exist *.* fails


#1
February 8, 2020 at 11:24:11
But the directory is never empty! There are always the directories . and .. in any directory (except the root directory, which only contains the first of these). Both * and *.* match these two directories.

Reply ↓  Report •

#2
February 8, 2020 at 19:59:40
Directory of C:\Temp\mytest

08/02/2020 14:28 <DIR> .
08/02/2020 14:28 <DIR> ..
0 File(s) 0 bytes
2 Dir(s) 108.083.978.240 bytes free


Right there's you problem, as you can see. Unless your in root of drive,
the two "dots" will always be there. If you just want to remove the subdir,
a simple rd will prevent that without testing, as you know,
ECHO N | RD /S MYTEST||echo DIRECTORY NOT EMPTY
it will complain or 'query' y/n. If you want a true test, a few bytes more code:
(for /f %%a in ('dir /b /a mytest') do set empty=n)||set empty=y

In place of the 'set empty=', you could substitute a call or a jump.

message edited by nbrane


Reply ↓  Report •

#3
February 10, 2020 at 00:28:27
That's what I was fearing, which is a bit of a shame since now it is a useless test. It basically confirms you are having a file system ..

I think it is a bug, based on 2 things:
1. documentation: The "IF EXIST filename" function is described as: "Specifies a true condition if the specified filename exists."

I'm even counting NORMAL directories as "files", but I'm not counting the current . or .. itself because those are NOT files or directories one can make. They are reserved words, and as such are not either a file or a directory. They refer to directories all right, a bit like shortcuts do, but they themselves are not files or directories.

2. Logic: anything that is always present inside a directory, from the moment you make it, until the deletion of it, cannot be considered as content, but as part of the structure itself. Otherwise, one would never have an empty directory. If you do a DIR in such a directory, it states:

0 File(s) 0 bytes

Well, that is because there are 0 files, holding 0 bytes, which in English means: empty.


Reply ↓  Report •

Related Solutions

#4
February 10, 2020 at 05:30:35

I'm afraid that your logic in 2) is flawed. As you say, the directory listing specifies 0 Files(s) and 0 bytes. But it would do the same if you had a directory, and no files, within the directory you are testing. So that doesn't mean that the directory is empty.

The point is that "if exist" is designed to find if a specific file or directory name exists. If you specify that any name is allowed you will always get the answer "yes".

A Google search will reveal the correct way to test if a directory contains other than the default directories.


Reply ↓  Report •

#5
February 10, 2020 at 06:31:36
> I'm afraid that your logic in 2) is flawed. As you say, the directory listing
> specifies 0 Files(s) and 0 bytes. But it would do the same if you had a
> directory, and no files, within the directory you are testing. So that
> doesn't mean that the directory is empty.
>

Hmm, forgot about that
But I've found something else: Windows Explorer does state "This folder is empty." if you have no files or folders, in a folder. So that contradicts the "IF EXIST" command ... And one can only be true.


Reply ↓  Report •

#6
February 10, 2020 at 06:35:14
> The point is that "if exist" is designed to find if a specific file or directory
> name exists. If you specify that any name is allowed you will always
> get the answer "yes".
>

Yes, that is the summary, but that confirms it is wrong, as it contradicts with the concept of "an empty folder", which is what you have after creating one, and not putting anything in it.

> A Google search will reveal the correct way to test if a directory contains
> other than the default directories.

That's no problem, I see that "DIR /B" always responds correctly, so that is covered.


Reply ↓  Report •

#7
February 10, 2020 at 20:23:12
Ha! This is a great thread, touching as it does on the existentail question: "Do I contain myself?" I think most philosophers, mathematicians, topologists, and cosmologists would tend to "no": An entity cannot "contain" itself because it is exactly itself, and not any larger, nor topologically/morphologically divergent.. Very Tao.
In this respect, I totally agree with looge that this is a "bug" in cmd.exe. The ".." is completely out of bounds. That would be like me saying that I contain the universe or god that created me and of which I am only a subset. That is definitely impossible according to non-mystical logic
(won't go further than that, here!).
So, back to the dot: the single dot should not, (imho) qualify as "content", and I agree that these are only symbolic references that have no practical or conceptual relevance to what is essentially being asked, at least in terms of data storage.
But if I am "dot", and I ask myself, do I exist, I would usually, or at least on a good day, say "yes". But that still leaves the question, if I contain no files or subdirs, that I exist but nothing else exists within me, then do I exist? "Yes" as an entry in the filesystem.
But do I have any content? "No, because all I am is an entry in the filesystem" (even thought that DOES contain information such as creation-date and attributes).

message edited by nbrane


Reply ↓  Report •

#8
February 10, 2020 at 23:16:33
The misconception here is that you are treating a directory as a physical container, containing physical objects. But it is not; a directory is a list of pointers to files and other directories.

Consider what happens when you move a file from one directory to another on the same disk. Do you have to move the data to a new location? No - you just remove the pointer from the source directory and create a new pointer in the destination directory.

What about linked files? Does this mean there are two copies of the file in the two directories? Again, no.

Or what about (what would be) a really paradoxical situation. You have a 100MB disk with a directory A. Within that directory you have another directory B on which you have mounted a 100GB disk. Does directory A now contain 100GB of data on a 100MB disk?

The answers to these questions are trivial when you treat directories as what they are - lists of pointers. And, as such, it makes perfect sense for them to contain a pointer to themselves and to the parent directory. It would be very difficult to navigate the file system otherwise.

Now, what you mean by "Is a directory empty" is another question. When it comes to file system utilities, most of them treat a directory that only contains those two default pointers as being empty. But when it comes to enumerating the contents with wildcards, all entries are returned. This isn't a bug, it's just a choice that the designers of the system made. And a user needs to understand those choices and use the appropriate utilities for the appropriate purposes.


Reply ↓  Report •

#9
February 11, 2020 at 19:16:14
Good answer ijack. It seems to be mostly a difference of semantics, and intent of the person asking the question. Like I, and looge mentioned, the dots are a symbolic reference, like links where two pointers point to the same exact cluster. Those links constitute "content" in that they store information, but they're kind of like ghosts, because if the cluster got wiped they would point to nothing. The filesystem pointers are, as you said, the same concept. Of course we know the directory does not "contain" the files themselves, it's just an "index". The index does contain information, but only enough to get to the real data. Most of us know, from sad and painful experience, how useless those pointers become when a disk is failing. But your conclusion was correct: it's not a "bug" per se, it's just different points of view and based on different objectives, and it's not a big deal to code for the one you're after.

Reply ↓  Report •

#10
February 12, 2020 at 08:22:03
> Now, what you mean by "Is a directory empty" is another
> question.

I basically don't need to: Microsoft - through the Windows Explorer is confirming my thought exactly:
Create a directory, don't do anything in it: voila, an empty directory.
It's just the IF EXIST function that is wrong.

> When it comes to file system utilities, most
> of them treat a directory that only contains those two
> default pointers as being empty. But when it comes to
> enumerating the contents with wildcards, all entries
> are returned. This isn't a bug, it's just a choice
> that the designers of the system made.

I think it's a bug
And that is because the "things" he finds are not files or directories INSIDE the directory structure I'm looking.
The dot is the current directory ... I don't need to check if it exists, when I'm navigated in it. Since, I can't navigate to a non-existant directory, can you ?
And the double dot is even more irrelevant: It basically states my current directory, is located in another directory
(unless I'm in root)
Also here: if I'm in a directory, I don't need conformation that the directory below the current one exists, that is a 100% guarantee.

It's like I stated in the beginning: it is confirming I am in a file system. I sort of knew that already ..

> And a user
> needs to understand those choices and use the
> appropriate utilities for the appropriate purposes.

Ow sure, when you read the documentation, you will .. smell that ? Or, by which sense will people "know" it ?
By the fact that Microsoft will deny it's a bug ?
By the fact it is documented ? ( it isn't )

I've made my own "IF EXIST", it's sort of this:

and it reports everything correctly, including usage of * and *.*

set p_files2lookfor=%1
set p_commandonly=%2
set p_command2run=%2 %3 %4 %5 %6 %7 %8 %9

set p_found=no

for /F %%A in ( ' dir %p_files2lookfor% /B 2^> nul ' ) do set p_found=yes

echo Found files? %p_found%

if defined p_commandonly if %p_found%+==yes+ call :run_command

goto :EOF

:run_command
%p_command2run%
goto :EOF

message edited by Looge


Reply ↓  Report •

#11
February 12, 2020 at 08:30:46
> What about linked files? Does this mean there are two copies
> of the file in the two directories? Again, no.

A link, technically possible although unusual in Windows, is considered another object:
- directory
- file
- link

So, if you query content, and he doesnt' differ between directory or file, why would he differ with another object still ? Cause it is a copy ? Hmm, it's an object, and it is a valid object inside a directory. It's not a semantic reference to another real object (like . and ..), it's a real object, with its own properties, even when it points to another file, directory or link.

But that is less relevant, as it makes things even more difficult. I'm sure there are many bugs if you perform basic Windows commands on symbolic links, but that is a price to pay. Normal users don't create links, so their existance is rare.


Reply ↓  Report •

#12
February 12, 2020 at 08:34:56
> Or what about (what would be) a really paradoxical situation.
> You have a 100MB disk with a directory A. Within that
> directory you have another directory B on which you have
> mounted a 100GB disk. Does directory A now contain
> 100GB of data on a 100MB disk?

I'm not sure how you mount a disk INSIDE a folder in Windows.
In Linux yes, in Unix, yes, but I'm not sure what you are doing there ...
In Windows, drive letters are mounts, or partitions. You can't mount a disk within a disk, like is possible in Linux or Unix.

And even if you could: it's not relevant as the IF EXISTS looks for files. It does not care what device the files or directories are on. Not saying physical disks are not relevant, but not for a function that checks on existance.


Reply ↓  Report •

#13
February 12, 2020 at 09:26:50
I'll grant that you don't understand how to mount a filesystem on a directory in Windows. But that's a reflection of your lack of understanding, not of the way filesystems work.

(Hint have a look at the option to assign a letter to a partition in Disk Manager. Also checkout: https://docs.microsoft.com/en-us/wi... )


Reply ↓  Report •

#14
February 12, 2020 at 20:18:30
I guess a pointer, or "entry", could point to an entry in another subir, which points to an entry in another subdir, that points to an entry... What if, like oroboros, the snake swallows it's own tail? I'm sure Microsoft and Linux have circumvented that eventuality. My position is that there needs to be a way to distinguish between pointers that point to other pointers, and pointers that actually point to the core target. If I erase all the subdirs that contain only pointers on my drive, other than the "actual" ones, I can still retrieve those files from their "root" directory, and of course if I destroy that root pointer, then I've closed the door on that particular file. But, per ijack latest, if I did mount a filesystem on a directory, and then delete it, I would assume (and hope) that it does not actually delete that filesystem, but only it's reference. I think this is the critical distinction. F/e, if I issue a delete, or worse yet, a 'rd /s /q' against a "fundamental" pointer, that is much more serious than deleting a secondary index entry. Then I googled to mklink. I did experiments, but now I'm more confused. It seems like mklink makes a copy, and not a pointer. Modifying the mlink reference does not modify either the original nor the linked file....

message edited by nbrane


Reply ↓  Report •

#15
February 13, 2020 at 01:49:44
The situation is further complicated by the fact that there are soft links and hard links (much like the same entities in Unix) and junction points. The wiki article https://en.wikipedia.org/wiki/NTFS_... gives a good summary.

In essence "." and ".." are symbolic links to the appropriate directories, and so have just as much relevance as any other symbolic link in a directory.

I think what this discussion illustrates is what a limited tool batch commands are in modern Windows. For serious use the MFC CFileFind class is much more versatile. One of its methods is CFindFile::IsDots which tests whether the found file is one of "." or "..". Perfect!


Reply ↓  Report •

#16
February 21, 2020 at 07:41:22
> I'll grant that you don't understand how to mount a filesystem on
> a directory in Windows. But that's a reflection of your lack of
> understanding, not of the way filesystems work.
>
> (Hint have a look at the option to assign a letter to a partition in
> Disk Manager. Also checkout:
> https://docs.microsoft.com/en-us/wi... )
>

Oh, but I do, since I am using these things on both Unix and Linux machines
But what that page states, is that you create a directory on a given drive, that POINTS to an EXISTING other drive. ( A drive letter )

That is not a mountpoint, that is a shortcut, because the physical drive is already mounted.

This is like using SUBST, isn't it ? Has nothing to do with mounting drives ...


Reply ↓  Report •

#17
February 21, 2020 at 07:49:58
> I think what this discussion illustrates is what a limited tool batch commands
> are in modern Windows. For serious use the MFC CFileFind class is much
> more versatile. One of its methods is CFindFile::IsDots which tests whether
> the found file is one of "." or "..". Perfect!
>

Not really.

Batch scripting IS LIMITED, I agree with that, but the issue being stumbled upon is actually not related to a limit of batch scripting. A batch script can perfectly do what is requested, that is: determining if a directory is empty or not. In my solution I just used a FOR command for that. Not really exotic or far fetched, is it ?

But, I need to do that, because the standard IF statement has a bug. This has nothing to do with limitations, it's a pure bug.


Reply ↓  Report •

#18
February 21, 2020 at 08:08:35
> In essence "." and ".." are symbolic links to the appropriate directories,
> and so have just as much relevance as any other symbolic link in a
> directory.
>

No, they are reserved words that act like a symbolic link

Windows says . and .. are directories

21/02/2020 17:07 <DIR> .
21/02/2020 17:07 <DIR> ..
21/02/2020 16:40 0 ttt
21/02/2020 17:07 <JUNCTION> twe [C:\temp\ttt]
21/02/2020 17:07 <SYMLINK> twe2 [C:\temp\ttt]


Reply ↓  Report •

#19
February 21, 2020 at 08:54:35
#16 "But what that page states, is that you create a directory on a given drive, that POINTS to an EXISTING other drive. ( A drive letter )"

That is incorrect (and I agree that the reference is misleading). I have Windows drives mounted on directories without having an assigned drive letter. Try it and see. Theory is fine, but practice is definitive.

Argue all you like - Eppur si muove


Reply ↓  Report •

#20
February 21, 2020 at 17:57:35
I agree with looge that the dots should not count in *.*. It's counter-intuitive and too anal.
I believe that the essential distinction of "existence" is whether the entity in question is
deletable, or desctructible, from the asker's current location in filespace. If I can (with
adequate permissions of course) delete (even potentially) the entity in question, (using only the handle in question), then that establishes existence for practical application. I can't delete "." or ".." If any index or reference points to some other entry which allows me to delete or modify that set of data, then it "exists" in my sphere of influence. If it is just a link or "junction", but allows me this destructive or mutative influence, then yes, it must be treated as existing for me. But if you mapped an extended subdirectory, or even and entire disk, to a single reference in some corner of filespace, I would hope that you could not delete it. f/e: map c:\ to "junk" in a subdirectory on D:, and you typed in: "rd /s /q junk", one would really really hope that this would not occur! But would be instead like deleting shortcuts from your desktop.

Reply ↓  Report •

#21
February 21, 2020 at 22:51:23
We can all have our views upon how a particular Windows command should behave, but I have to be more concerned with how they do behave. And in Windows *.* returns all files and directories, including "." and "..". This is what you have to work with.

That this is not a bug but a design decision is evidenced by the behaviour of the C API. The "FindFile" function will include these two directories in its results. But, as I said earlier, there is a separate function to test if a directory is one of these two.

By all means write your own OS incorporating your own design decisions, but it's unfair to label the decisions of the Windows designers as "bugs".


Reply ↓  Report •

#22
February 22, 2020 at 01:44:56
As to the question of "existence", I think there is a confusion here as to what "exist" tests for. It's not testing for a physical file on a disk, but for an entry in a directory. Are there entries in the directory for "." and ".."? Of course there are. These directory entries "exist".

It's true that you can't delete "." or "..". But this is not because they don't exist, but because they are in use when you try to delete them. Try it and see (experiment is always the best teacher) - look what error message you get. As for deleting a mounted filesystem and its mount directory, I've never tried this is Windows. But I have in UNIX - and it does exactly what I would expect it to.


Reply ↓  Report •

#23
February 22, 2020 at 22:49:50
Ok. "you're both right", depending... I tried another test, using only a file, "c", and these gave interesting results: "if exist c\" yielded false. "If exist c\." yielded true, even though "c" was not a directory but a file. ("c" is in the cwd and had a couple bytes content, cwd is otherwise empty). Other tests "If exist":
*.*\ false
*\ false
*\. true
*.*\. true
*.* true
The slash, without the dot, yielded one interpretation, and the slash with the dot yielded the opposite. Applied to a file, the slash should not even apply!

Reply ↓  Report •

Ask Question