¿Qué hace if (- f) en Perl?


Me encontré con esta línea de código:

if( -f <filename> ) { ... }

-f parece probar si el nombre del archivo existe o no, pero no estoy seguro. Googlear no ha ayudado hasta ahora (es difícil buscar en Google "-f") y tampoco lo han hecho mis libros de Perl.

¿Alguien puede aconsejar?

 25
Author: Peter Mortensen, 2011-05-30

5 answers

Véase perlfunc.

Enumera todas las funciones integradas en Perl, incluidas las de "prueba de archivos":

-X FILEHANDLE
-X EXPR
-X DIRHANDLE
-X

Donde -X es una de las siguientes:

-r: File is readable by effective uid/gid.
-w: File is writable by effective uid/gid.
-x: File is executable by effective uid/gid.
-o: File is owned by effective uid.

-R: File is readable by real uid/gid.
-W: File is writable by real uid/gid.
-X: File is executable by real uid/gid.
-O: File is owned by real uid.

-e: File exists.
-z: File has zero size (is empty).
-s: File has nonzero size (returns size in bytes).

-f: File is a plain file.
-d: File is a directory.
-l: File is a symbolic link.
-p: File is a named pipe (FIFO), or Filehandle is a pipe.
-S: File is a socket.
-b: File is a block special file.
-c: File is a character special file.
-t: Filehandle is opened to a tty.

-u: File has setuid bit set.
-g: File has setgid bit set.
-k: File has sticky bit set.

-T: File is an ASCII text file (heuristic guess).
-B: File is a "binary" file (opposite of -T).

-M: Script start time minus file modification time, in days.
-A: Same for access time.
-C: Same for inode change time (Unix, may differ for other platforms)
 30
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-22 12:07:47

En Unix, los directorios pueden contener los siguientes tipos de archivos:

  • Simple (lo que considerarías un archivo)
  • Directorio
  • Tubería con nombre
  • Socket con nombre
  • ...

-f prueba si el nombre proporcionado hace referencia a un archivo que es un archivo plano. Devolverá undef (error ENOENT) si el archivo no existe, o algunos otros valores falsos si el archivo existe pero no es un archivo simple (por ejemplo, si es un directorio).

-X operadores

 6
Author: ikegami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-30 07:02:05
 4
Author: Jason Iverson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-22 12:13:53

if (-f <filename> ) { ... }

Parece que o he malinterpretado la pregunta, o todo el mundo lo ha hecho.

Primero, hagamos algunas suposiciones.

  1. Supongamos que no ha sobrecargado todos los operadores unarios de prefijo -X (es todos o ninguno de ellos),

  2. Supongamos también que no ha sobrecargado el operador de iteración circunfijo <>.

Suponiendo que ambos de esos dos givens dado lo anterior shoul hold, entonces la notación <filename> hará un scalar readline(*filename) - que depende del valor de $/ - y luego pasará ese resultado al operador filetest para su posterior evaluación, generalmente pero no necesariamente por medio de stat (2). Eso significa que es mejor tener un filehandle abierto con el nombre de filename para que esto funcione, a menos que se trate de una verdadera magia profunda.

If también hará esto para <$filename>, excepto que ahora $filename es un identificador indirecto en lugar de uno directo como filename. De nuevo, $/ es respetado. El uso de un nombre de archivo propio para el filehandle asociado con él es en realidad algo que hago todo el término. Por ejemplo:

our $fn = "/etc/termcap";
open($fn, "<", $fn) || die "can't open $fn: $!";

De esa manera los mensajes warn y die realmente me dicen el nombre del archivo. Por ejemplo:

while (<$fh>) {
     warn "oops" if whatever;
}

Me dirá el número de línea y el nombre del archivo en el que opté.

Ahora, si el operando de <⋯> se desvía de las reglas para objetos dativos permitidos sin corchete, es decir, un prefijo bareword por cero o más signos de dólar, entonces no es el operador de iteración sino el comodín burster. Esto es cierto incluso sin comodines. Solo tiene que violar la famosa Regla de Dativos de Perl, y eso luego desencadena la alternativa {[26]]}

Esto significa que si y solo si filename no es un bareword legal con cero o más signos de dólar principales , como por ejemplo /etc/termcap, /tmp, *.[Cchy], {,/usr}/bin/c?, o ~/Documents - entonces ese viejo operador de conglobulación familiar en la guía del File::Glob::bsd_glob se llama a la función en su lugar, con exactamente el tipo de resultado que se esperaría de una función tan útil y comúnmente utilizada cuando se suministra con el argumento apropiado.

Aquí hay muchos ejemplos que muestran respuestas al tipo de pregunta que la porción citada arriba está haciendo: {[26]]}

use v5.10;  # for the say feature, but not needed for conglobulation

if (-d <~joebob>                 ) { say "joebob has a home"                 }
if (-d <~joebob/.opera>          ) { say "joebob has an opera directory"     }
if (-d <~joebob/.ssh>            ) { say "joebob has an ssh directory"       }

if ($n = grep {-e} <~joebob/.*rc>) { say "joebob has $n RC files"            }

if (-f <~joebob/.exrc>           ) { say "joebob has a vi config file"       }
if (-f <~joebob/.profile>        ) { say "joebob has a sh profile"           }
if (-f <~joebob/.bashrc>         ) { say "joebob has a bash config script"   }
if (-f <~joebob/.cshrc>          ) { say "joebob has a csh config script"    }
if (-f <~joebob/.log{in,out}*>   ) { say "joebob has csh login/out scripts"  }

if (-S </tmp/.X*/X*>             ) { say "I smell an X11 socket"             }

if (-t STDIN && -t STDOUT        ) { say "smells pretty tty to me"           } 
 2
Author: tchrist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-30 18:54:01

Prueba si el objeto especificado por <filename> es un archivo plano (en lugar de binario, o ser un directorio, etc.).

 -3
Author: Jake Petroules,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-30 06:34:38