Method: Kernel#test

Defined in:
file.c

#test(*args) ⇒ Object

:markup: markdown

call-seq:

test(char, path0, path1 = nil) -> object

Performs a test on one or both of the filesystem entities at the given paths ‘path0` and `path1`:

  • Each path ‘path0` or `path1` points to a file, directory, device, pipe, etc.

  • Character ‘char` selects a specific test.

The tests:

  • Each of these tests operates only on the entity at ‘path0`, and returns `true` or `false`; for a non-existent entity, returns `false` (does not raise exception):

    | Character    | Test                                                                      |
    |:------------:|:--------------------------------------------------------------------------|
    | <tt>'b'</tt> | Whether the entity is a block device.                                     |
    | <tt>'c'</tt> | Whether the entity is a character device.                                 |
    | <tt>'d'</tt> | Whether the entity is a directory.                                        |
    | <tt>'e'</tt> | Whether the entity is an existing entity.                                 |
    | <tt>'f'</tt> | Whether the entity is an existing regular file.                           |
    | <tt>'g'</tt> | Whether the entity's setgid bit is set.                                   |
    | <tt>'G'</tt> | Whether the entity's group ownership is equal to the caller's.            |
    | <tt>'k'</tt> | Whether the entity's sticky bit is set.                                   |
    | <tt>'l'</tt> | Whether the entity is a symbolic link.                                    |
    | <tt>'o'</tt> | Whether the entity is owned by the caller's effective uid.                |
    | <tt>'O'</tt> | Like <tt>'o'</tt>, but uses the real uid (not the effective uid).         |
    | <tt>'p'</tt> | Whether the entity is a FIFO device (named pipe).                         |
    | <tt>'r'</tt> | Whether the entity is readable by the caller's effective uid/gid.         |
    | <tt>'R'</tt> | Like <tt>'r'</tt>, but uses the real uid/gid (not the effective uid/gid). |
    | <tt>'S'</tt> | Whether the entity is a socket.                                           |
    | <tt>'u'</tt> | Whether the entity's setuid bit is set.                                   |
    | <tt>'w'</tt> | Whether the entity is writable by the caller's effective uid/gid.         |
    | <tt>'W'</tt> | Like <tt>'w'</tt>, but uses the real uid/gid (not the effective uid/gid). |
    | <tt>'x'</tt> | Whether the entity is executable by the caller's effective uid/gid.       |
    | <tt>'X'</tt> | Like <tt>'x'</tt>, but uses the real uid/gid (not the effective uid/git). |
    | <tt>'z'</tt> | Whether the entity exists and is of length zero.                          |
    
  • This test operates only on the entity at ‘path0`, and returns an integer size or nil:

    | Character    | Test                                                                                         |
    |:------------:|:---------------------------------------------------------------------------------------------|
    | <tt>'s'</tt> | Returns positive integer size if the entity exists and has non-zero length, +nil+ otherwise. |
    
  • Each of these tests operates only on the entity at ‘path0`, and returns a Time object; raises an exception if the entity does not exist:

    | Character    | Test                                   |
    |:------------:|:---------------------------------------|
    | <tt>'A'</tt> | Last access time for the entity.       |
    | <tt>'C'</tt> | Last change time for the entity.       |
    | <tt>'M'</tt> | Last modification time for the entity. |
    
  • Each of these tests operates on the modification time (‘mtime`) of each of the entities at `path0` and `path1`, and returns a `true` or `false`; returns `false` if either entity does not exist:

    | Character    | Test                                                            |
    |:------------:|:----------------------------------------------------------------|
    | <tt>'<'</tt> | Whether the `mtime` at `path0` is less than that at `path1`.    |
    | <tt>'='</tt> | Whether the `mtime` at `path0` is equal to that at `path1`.     |
    | <tt>'>'</tt> | Whether the `mtime` at `path0` is greater than that at `path1`. |
    
  • This test operates on the content of each of the entities at ‘path0` and `path1`, and returns a `true` or `false`; returns `false` if either entity does not exist:

    | Character    | Test                                          |
    |:------------:|:----------------------------------------------|
    | <tt>'-'</tt> | Whether the entities exist and are identical. |
    
[View source]

5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
# File 'file.c', line 5516

static VALUE
rb_f_test(int argc, VALUE *argv, VALUE _)
{
    int cmd;

    if (argc == 0) rb_check_arity(argc, 2, 3);
    cmd = NUM2CHR(argv[0]);
    if (cmd == 0) {
        goto unknown;
    }
    if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
        CHECK(1);
        switch (cmd) {
          case 'b':
            return rb_file_blockdev_p(0, argv[1]);

          case 'c':
            return rb_file_chardev_p(0, argv[1]);

          case 'd':
            return rb_file_directory_p(0, argv[1]);

          case 'e':
            return rb_file_exist_p(0, argv[1]);

          case 'f':
            return rb_file_file_p(0, argv[1]);

          case 'g':
            return rb_file_sgid_p(0, argv[1]);

          case 'G':
            return rb_file_grpowned_p(0, argv[1]);

          case 'k':
            return rb_file_sticky_p(0, argv[1]);

          case 'l':
            return rb_file_symlink_p(0, argv[1]);

          case 'o':
            return rb_file_owned_p(0, argv[1]);

          case 'O':
            return rb_file_rowned_p(0, argv[1]);

          case 'p':
            return rb_file_pipe_p(0, argv[1]);

          case 'r':
            return rb_file_readable_p(0, argv[1]);

          case 'R':
            return rb_file_readable_real_p(0, argv[1]);

          case 's':
            return rb_file_size_p(0, argv[1]);

          case 'S':
            return rb_file_socket_p(0, argv[1]);

          case 'u':
            return rb_file_suid_p(0, argv[1]);

          case 'w':
            return rb_file_writable_p(0, argv[1]);

          case 'W':
            return rb_file_writable_real_p(0, argv[1]);

          case 'x':
            return rb_file_executable_p(0, argv[1]);

          case 'X':
            return rb_file_executable_real_p(0, argv[1]);

          case 'z':
            return rb_file_zero_p(0, argv[1]);
        }
    }

    if (strchr("MAC", cmd)) {
        struct stat st;
        VALUE fname = argv[1];

        CHECK(1);
        if (rb_stat(fname, &st) == -1) {
            int e = errno;
            FilePathValue(fname);
            rb_syserr_fail_path(e, fname);
        }

        switch (cmd) {
          case 'A':
            return stat_atime(&st);
          case 'M':
            return stat_mtime(&st);
          case 'C':
            return stat_ctime(&st);
        }
    }

    if (cmd == '-') {
        CHECK(2);
        return rb_file_identical_p(0, argv[1], argv[2]);
    }

    if (strchr("=<>", cmd)) {
        struct stat st1, st2;
        struct timespec t1, t2;

        CHECK(2);
        if (rb_stat(argv[1], &st1) < 0) return Qfalse;
        if (rb_stat(argv[2], &st2) < 0) return Qfalse;

        t1 = stat_mtimespec(&st1);
        t2 = stat_mtimespec(&st2);

        switch (cmd) {
          case '=':
            if (t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec) return Qtrue;
            return Qfalse;

          case '>':
            if (t1.tv_sec > t2.tv_sec) return Qtrue;
            if (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec) return Qtrue;
            return Qfalse;

          case '<':
            if (t1.tv_sec < t2.tv_sec) return Qtrue;
            if (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec) return Qtrue;
            return Qfalse;
        }
    }
  unknown:
    /* unknown command */
    if (ISPRINT(cmd)) {
        rb_raise(rb_eArgError, "unknown command '%s%c'", cmd == '\'' || cmd == '\\' ? "\\" : "", cmd);
    }
    else {
        rb_raise(rb_eArgError, "unknown command \"\\x%02X\"", cmd);
    }
    UNREACHABLE_RETURN(Qundef);
}