Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Don't do that, it's not only subject to race conditions, but also the <code>[ -e /path/file ]</code> checks if you can do a <code>stat(2)</code> on a file, so it will return false for different reasons, not only because the file cannot exist.</p> <p>An example is a symlink to a file that doesn't exist or a file in a directory you don't have search permission to.</p> <p>A much better approach is to use the right flags to the <code>open(2)</code> system call here, that is <code>O_CREAT|O_EXCL</code>. That way, the <code>open()</code> fails if the file didn't already exist without you having to do the check several millions of CPU clock ticks earlier.</p> <p>With a Bourne-like shell:</p> <pre><code>if (set -C &amp;&amp; : &gt; "$file") 2&gt; /dev/null; then print '%s\n' "$file has been created else print '%s\n' "It hasn't, possibly because it was already there" fi </code></pre> <p>(<code>set -C</code> is to enable the <code>O_EXCL</code> flag).</p> <p>Also, why would you want to create an empty file? Chances are you want to store something in that file. Then, just do it:</p> <pre><code>set -C { echo blah other-commands that-generate-the-content } &gt; "$file" </code></pre> <p>Then, that command group is only executed if the <code>file</code> didn't exist already (and it was possible to create it).</p> <p>If you want to test for file existence, write it at least:</p> <pre><code>[ -e "$file" ] || [ -L "$file" ] </code></pre> <p>or</p> <pre><code>ls -d -- "$file" &gt; /dev/null 2&gt;&amp;1 </code></pre> <p>if you care about it potentially being a symlink. That will still return false if the file does exist but you don't have the right to verify it.</p> <hr> <p>Now, if you want a longer and historical answer about testing for file existence:</p> <p>Initially, the <code>test</code> command (in Unix v7 where it first appeared) <a href="http://www.freebsd.org/cgi/man.cgi?manpath=v7&amp;query=test" rel="nofollow">had no <code>-e</code> (nor <code>-h</code>/<code>-L</code> option or <code>-a</code> unary)</a> option.</p> <p>The way to test for file existence was with <code>ls</code>. <code>ls</code> (with <code>-d</code>) lists the file and reports an error (and returns a <em>false</em> exit status) if it can't look up the file for a reason or another. Unix initially didn't have symlinks, but when they were introduced, <code>ls</code> was modified to do a <code>lstat(2)</code> on a file instead of a <code>stat(2)</code>. That is, in case of symlink <code>ls</code> returns information about the symlink file itself, not the file at the path the symlink points to.</p> <p>An option to <code>test</code> (aka <code>[</code>) for testing for file <em>"existence"</em> was first introduced in the <a href="http://www2.research.att.com/sw/download/man/man1/ksh88.html" rel="nofollow">Korn shell <code>test</code> builtin</a>. That was <code>-a</code>, not <code>-e</code>. <code>-a</code> is for <em>accessible</em> (I believe) which is a more accurate term than <em>existing</em>.</p> <p>I don't know when or what introduced <code>-e</code>, possibly POSIX. POSIX <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html" rel="nofollow">says</a> that <code>-e</code> was chosen over <code>-a</code> to avoid the possible confusion with the <code>-a</code> <em>binary</em> operator (for <em>and</em>).</p> <p>In any case both <code>-a</code> and <code>-e</code> attempt a <code>stat(2)</code> on the file, not a <code>lstat(2)</code>. That is:</p> <pre><code>[ -e "$file" ] </code></pre> <p>is equivalent to:</p> <pre><code>ls -Ld -- "$file" &gt; /dev/null 2&gt;&amp;1 </code></pre> <p>So, strictly speaking, it returns true if, at the time the test was done, it was possible to lookup the path after resolving the symlinks, and if the <code>stat(2)</code> fails, the reason for the failure is ignored.</p> <p><code>stat</code> may fail if the file doesn't exist (<code>ENOENT</code>), that is if the file doesn't exist or it exists but is a symlink to a file that doesn't exist, but also for plenty other reasons. Looking at <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html#tag_16_174_05" rel="nofollow">the possible error codes of <code>stat(2)</code></a> gives a few ideas:</p> <ul> <li><code>EACCESS</code>: during resolution of the path (and that can be any path component and in the path of any symlink), you don't have <em>search</em> permission for one directory component (note that you may still have access to the file via another path).</li> <li><code>ELOOP</code>: impossible to resolve the path because of too many symlinks resolved to get there.</li> <li><code>ENOTDIR</code>. For instance on <code>/etc/passwd/foo</code> or a symlink to it.</li> </ul>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload