Función PHP – Extraer ruta, nombre y extensión de un archivo

La curiosidad me la ha despertado el viciño r0sk en su blog a partir de las diferentes opciones que él y sus compañeros de trabajo (saludos a todos de mis partes!) han desarrollado para extraer información de una ruta, nombre y extensión de un archivo dado. Asi que a ellos, a él y a su señora les dedico este post/opinión.

Planteamiento

Algo que en principio parece tan trivial, se complica si empezamos a pensar en las diferentes posibilidades de uso (o mal uso) de una función de este tipo:

  • Extensión sin nombre: .htaccess
  • Nombre sin extensión: name
  • Nombre simplón: name.jpeg
  • Nombre complejo: name.surname.gif
  • Ruta absoluta: /path/to/name.surname.tar.gz
  • Ruta relativa: ../../path/to/name.surname.tar.gz
  • BONUS: Cadena vacia para romper la función Comillas vacias ''
  • BONUS 2: Cadena malformada para romper la función '/\/.path///file/.gif'
  • BONUS 3: Ruta sin archivo '/path/to/folder/'

Requerimientos

Si además queremos aumentar los requerimientos, la cosa se puede complicar bastante:

  • Yo como soy un perfeccionista de mierda, quiero 7 Campos:
    • ¿ El fichero existe ? Puede ser útil en caso de querer borrar/comprobar
    • ¿ El fichero es escribible ? Puede ser útil en caso de querer borrar/editar
    • Los permisos del archivo en formato "humano"
    • El Nombre sin extensión
    • La Extensión sin nombre
    • El Archivo (nombre+extensión)
    • La Ruta
  • La función debe ser totalmente compatible hacia atrás, al menos cubriendo a PHP4
  • En la medida de lo posible, no quiero errores si el usuario me pasa datos no válidos
  • No quiero cadenas vacias, si uno de los campos no existe quiero un lindo FALSE
  • Quiero la ruta sin / al final, añadirla en otras partes del flujo de código es mucho más sencillo que tener que quitarla a posteriori.

Con las manos en la masa

Asi que tras un poco de trapicheo y consulta, he acabado con este engendro, que podría ser mucho más corto, pero cumple todos los requerimientos anteriores:

PHP:
  1. function filedata($path) {
  2.         // Vaciamos la caché de lectura de disco
  3.         clearstatcache();
  4.         // Comprobamos si el fichero existe
  5.         $data["exists"] = is_file($path);
  6.         // Comprobamos si el fichero es escribible
  7.         $data["writable"] = is_writable($path);
  8.         // Leemos los permisos del fichero
  9.         $data["chmod"] = ($data["exists"] ? substr(sprintf("%o", fileperms($path)), -4) : FALSE);
  10.         // Extraemos la extensión, un sólo paso
  11.         $data["ext"] = substr(strrchr($path, "."),1);
  12.         // Primer paso de lectura de ruta
  13.         $data["path"] = array_shift(explode(".".$data["ext"],$path));
  14.         // Primer paso de lectura de nombre
  15.         $data["name"] = array_pop(explode("/",$data["path"]));
  16.         // Ajustamos nombre a FALSE si está vacio
  17.         $data["name"] = ($data["name"] ? $data["name"] : FALSE);
  18.         // Ajustamos la ruta a FALSE si está vacia
  19.         $data["path"] = ($data["exists"] ? ($data["name"] ? realpath(array_shift(explode($data["name"],$data["path"]))) : realpath(array_shift(explode($data["ext"],$data["path"])))) : ($data["name"] ? array_shift(explode($data["name"],$data["path"])) : ($data["ext"] ? array_shift(explode($data["ext"],$data["path"])) : rtrim($data["path"],"/")))) ;
  20.         // Ajustamos el nombre a FALSE si está vacio o a su valor en caso contrario
  21.         $data["filename"] = (($data["name"] OR $data["ext"]) ? $data["name"].($data["ext"] ? "." : "").$data["ext"] : FALSE);
  22.         // Devolvemos los resultados
  23.         return $data;
  24. }

Resultado y demostración

Puedes ver una demostración del uso de esta función en vivo y en directo en la dirección http://www.propiedadprivada.com/lab/phproute/

O bien comprobar el resultado aqui mismo:


Extensión sin nombre: .htaccess

Array (7)
(
|    ['exists'] = Boolean(1) TRUE
|    ['writable'] = Boolean(0) FALSE
|    ['chmod'] = String(4) " 0644 "
|    ['ext'] = String(8) " htaccess "
|    ['path'] = Boolean(0) FALSE
|    ['name'] = Boolean(0) FALSE
|    ['filename'] = String(9) " .htaccess "
)


Nombre sin extensión: name

Array (7)
(
|    ['exists'] = Boolean(1) TRUE
|    ['writable'] = Boolean(0) FALSE
|    ['chmod'] = String(4) " 0644 "
|    ['ext'] = Boolean(0) FALSE
|    ['path'] = Boolean(0) FALSE
|    ['name'] = String(4) " name "
|    ['filename'] = String(4) " name "
)


Nombre simplón: name.jpeg

Array (7)
(
|    ['exists'] = Boolean(1) TRUE
|    ['writable'] = Boolean(0) FALSE
|    ['chmod'] = String(4) " 0644 "
|    ['ext'] = String(4) " jpeg "
|    ['path'] = Boolean(0) FALSE
|    ['name'] = String(4) " name "
|    ['filename'] = String(9) " name.jpeg "
)


Nombre complejo: name.surname.gif

Array (7)
(
|    ['exists'] = Boolean(1) TRUE
|    ['writable'] = Boolean(0) FALSE
|    ['chmod'] = String(4) " 0644 "
|    ['ext'] = String(3) " gif "
|    ['path'] = Boolean(0) FALSE
|    ['name'] = String(12) " name.surname "
|    ['filename'] = String(16) " name.surname.gif "
)


Ruta absoluta:
/home/httpd/vhosts/propiedadprivada.com/httpdocs/lab/phproute/name.surname.tar.gz

Array (7)
(
|    ['exists'] = Boolean(1) TRUE
|    ['writable'] = Boolean(0) FALSE
|    ['chmod'] = String(4) " 0644 "
|    ['ext'] = String(2) " gz "
|    ['path'] = String(61) " /home/httpd/vhosts/propiedadprivada.com/httpdocs/lab/phproute "
|    ['name'] = String(16) " name.surname.tar "
|    ['filename'] = String(19) " name.surname.tar.gz "
)


Ruta absoluta que no existe: /path/to/myname.jpeg

Array (7)
(
|    ['exists'] = Boolean(0) FALSE
|    ['writable'] = Boolean(0) FALSE
|    ['chmod'] = Boolean(0) FALSE
|    ['ext'] = String(4) " jpeg "
|    ['path'] = String(9) " /path/to/ "
|    ['name'] = String(6) " myname "
|    ['filename'] = String(11) " myname.jpeg "
)


Ruta relativa: ../../lab/phproute/name.surname.tar.gz

Array (7)
(
|    ['exists'] = Boolean(1) TRUE
|    ['writable'] = Boolean(0) FALSE
|    ['chmod'] = String(4) " 0644 "
|    ['ext'] = String(2) " gz "
|    ['path'] = String(61) " /home/httpd/vhosts/propiedadprivada.com/httpdocs/lab/phproute "
|    ['name'] = String(16) " name.surname.tar "
|    ['filename'] = String(19) " name.surname.tar.gz "
)


BONUS: Cadena vacia para romper la función ''

Array (7)
(
|    ['exists'] = Boolean(0) FALSE
|    ['writable'] = Boolean(0) FALSE
|    ['chmod'] = Boolean(0) FALSE
|    ['ext'] = Boolean(0) FALSE
|    ['path'] = String(0) " "
|    ['name'] = Boolean(0) FALSE
|    ['filename'] = Boolean(0) FALSE
)


BONUS 2: Cadena malformada para romper la función '/\/.path///file/.gif'

Array (7)
(
|    ['exists'] = Boolean(0) FALSE
|    ['writable'] = Boolean(0) FALSE
|    ['chmod'] = Boolean(0) FALSE
|    ['ext'] = String(3) " gif "
|    ['path'] = String(16) " /\/.path///file/ "
|    ['name'] = Boolean(0) FALSE
|    ['filename'] = String(4) " .gif "
)


BONUS 3: Ruta sin archivo '/path/to/folder/'

Array (7)
(
|    ['exists'] = Boolean(0) FALSE
|    ['writable'] = Boolean(0) FALSE
|    ['chmod'] = Boolean(0) FALSE
|    ['ext'] = Boolean(0) FALSE
|    ['path'] = String(16) " /path/to/folder "
|    ['name'] = Boolean(0) FALSE
|    ['filename'] = Boolean(0) FALSE
)


11 comentarios a esta entrada

  • GravatarMario dijo
    el # Sábado, 16 de octubre del 2010 a las 18:54

    1

    Muchísimas gracias, me ha venido genial :-) un trabajo excelente.

  • Gravatardownly dijo
    el # Jueves, 9 de junio del 2011 a las 22:42

    2

    Buen script, funcional y entendible.
    ¿Existe alguna manera para validar qué tipo de archivo se está posteando… no en base a la cadena de archivo. Ya que podría enviar esto: archivo.exe.gif?
    Lo menciono porque se podría enviar un archivo con doble extensión con intensiones perjudiciales.
    Saludos

  • GravatarAngel Luis Ponce dijo
    el # Lunes, 21 de noviembre del 2011 a las 17:49

    3

    Cuando tu envias un archivo al servidor por el formulario con un input file este mismo maneja un array que dentro del mismo contiene un “type” donde se almacena el tipo de imagen, para hacer una comparativa sencilla seria asi:

    if ( ($_FILES["file_img"]["type"]) == ‘image/gif’){
    echo “Es una imagen con tipo GIF”;
    }else{
    echo “No es una imagen con tipo GIF”;
    }

    Espero te sirva, hay otro metodo que ahorita no recuerdo y ando corto de tiempo para buscarlo, pero es si me escribes a mi correo o entras a mi pagina para que nos comuniquemos y te envie con mas detalle el manejo de imagenes.

  • GravatarAngel Luis Ponce dijo
    el # Miércoles, 1 de febrero del 2012 a las 23:31

    4

    hay una funcion en php llamada imagemagick que te puede servir para la matipulación completa de imagenes, espero te sea util

  • GravatarHéctor dijo
    el # Sábado, 4 de febrero del 2012 a las 19:48

    5

    Ostia, esto está de puta madre xD

    ¡Gracias por tu tiempo y por esta función tan genial!

  • GravatarHéctor dijo
    el # Sábado, 4 de febrero del 2012 a las 20:03

    6

    Hay un detalle que es raro;

    Estoy gestionando la subida de un fichero, y al utilizar la función para recoger los datos de un archivo antes de moverlo, la ruta que me devuelve el Path es la ruta REAL, mientras que lo que hacía falta era la ruta TEMPORAL (ya que luego hay que moverlo).

  • Gravataricarolearning dijo
    el # Sábado, 17 de marzo del 2012 a las 04:10

    7

    Wuena, super útil.

  • Gravatarsaman dijo
    el # Martes, 22 de mayo del 2012 a las 15:56

    8

    me sirvio mucho niño :D gracias

  • Gravatarale dijo
    el # Sábado, 10 de noviembre del 2012 a las 07:18

    9

    hola.. una pregunta..como imprimes en html los valores que almacenaste en la variable data de filename, ???

  • GravatarAlejandro dijo
    el # Domingo, 2 de diciembre del 2012 a las 11:07

    10

    Muy buena aportación ;)

    Por algo los perfeccionistas son mucho más útiles.

  • GravatarAlejandro dijo
    el # Domingo, 2 de diciembre del 2012 a las 11:10

    11

    *Ale:

    Supongo que es más que obvio que cosas debes modificar.

Deja tu opinión

Sólo se permiten las etiquetas XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Post anteriores/siguientes:

Post (quizás) relacionados:

  • Breve guia para comprimir/empaquetar y descomprimir de un plumazo

  • Harto de buscar siempre lo mismo, aqui queda de recordatorio:Ficheros tar Empaquetar: tar -cvf archivo.tar /dir/a/comprimir/ Desempaquetar: tar -xvf archivo.tar Ver contenido tar -tf archivo.tar Ficheros gz Comprimir: gzip -9...
  • Dewplayer – Pequeñisimo reproductor mp3 en Flash gratuíto

  • Dewplayer es un pequeñisimo reproductor mp3 en flash gratuíto con el que podremos insertar ficheros MP3 en nuestras páginas de forma cómoda y rápida.Su inserción...
  • Linux: Extraer texto entre dos limitadores

  • Hoy me he encontrado en la tesitura de tener que extraer de un inmenso fichero de texto, unas sentencias SQL de una tabla concreta. Tras...
  • This Windows can break

  • Abre el Notepad de Windows (Inicio - Ejecutar - notepad - Enter) Escribe el texto "this windows can break" (sin comillas) Guarda el archivo con cualquier nombre Cierra...
  • Instalar PHP MagickWand bajo Windows – Xampp

  • MagicWand para PHP es un comodísimo módulo que nos permite acceder a parte de la API de ImageMagick, facilitándosnos el cambiar tamaño a imágenes, convertirlas...