help-gawk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How do I determine the existence (or non-existence) of a file from a


From: Emanuele Torre
Subject: Re: How do I determine the existence (or non-existence) of a file from an AWK script?
Date: Tue, 11 Apr 2023 01:09:50 +0200
User-agent: Mutt/2.2.10 (2023-03-25)

On Mon, Apr 10, 2023 at 03:40:06PM -0500, Neil R. Ormos wrote:
> fres will be 1 if the file exists and is a regular file; otherwise 0.  The -e 
> test might be appropriate in some cases.

Maybe, but keep in mind that both test/['s -f and -e are required to use
stat() instead of lstat() by POSIX, so they have some quirks:

* -f will be true for a path to a symbolic link that points to a regular
  file
* -e will be false for a path to a symbolic link that points to a file
  that does not exist ("broken symlink").
  So, even though the broken symbolic link exists at the path passed to
  -e, -e will be false; e.g.:

    $ ln -s falkdjldkf foolink
    $ ls -ld foolink
    lrwxrwxrwx 1 emanuele6 wheel 20 Apr 11 00:53 foolink -> falkdjldkf
    $ [ -e foolink ]; echo "$?"
    1

A way to work around this -e quirk is using..

    [ -e "$foo" ] || [ -L "$foo" ]

..instead of just [ -e "$foo" ]. (-L is a synonym of -h, and it is true
if the path specifies a symbolic link.)

Of course, it is not perfect since you are stating the file twice, and
the file could be replaced between the first and second stat, but it's
the best you can do only using standard test/[.

> Also, you will want to escape or quote the contents of foo, as required by 
> the shell, if foo is not guaranteed to be free of characters special to the 
> shell.  On my systems, calls to gawk's system() function run /bin/sh.  I 
> don't know if that's universal on all platforms.

It is standard that system() uses /bin/sh, yes.

You can easily quote a string to safely inject it in a system() command
using a function like this:

  function shquote (str) { gsub("'", "'\\''", str); return "'" str "'" }
  system("test -f " shquote($0)) == 0 {
    print
  }

With GNU awk, you can also use ENVIRON and avoid the injection, but note
that this is not standard, and doesn't work, for example, with nawk,
mawk, and busybox awk:

  { ENVIRON["foo"] = $0 }
  system("[ -e \"$foo\" ] || [ -L \"$foo\" ]") == 0) {
    print
  }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]