Listar elegantemente sólo los ficheros de un directorio

logo bash Bourne again shell

Extracto

Linux es un sistema maravilloso, pero con una sintaxis confusa, llena de parámetros. Tengo la costumbre de hacerme mis propios comandos, o bien, recrear aquéllos que uso de manera habitual con mi propia sintaxis. Es esta ocasión vamos a mejorar la salida del comando find para obtener una lista exclusivamente de los archivos que hay en un directorio dado.

@pedroruizhidalg― En esta ocasión vamos a usar PHP como motor de órdenes en BASH ya que la potencia de ejecución (y sintaxis) de BASH, aunque hay que conocerlas, no tenemos por qué «conformarnos» con ella. Aunque este script puede ser un poco farragoso, he querido mostrarlo precisamente porque en él convierto una lista de archivos en un array, opero con ese array, lo descompongo para cambiar de color y lo presento por pantalla. Además incluyo parámetros de ayuda y autor.

 

Descripción

La primera linea, llamada shebang, se usa para informar al sistema operativo que queremos usar PHP como lenguaje en el termina. Más información aquí. En realidad le pedimos a /usr/bin/env que nos proporcione la ruta de PHP.

Tras esto viene la declaración de inicio de sintaxis PHP, y tras los comentarios iniciales de rigor, se declaran las constantes que se usarán a lo largo del programa. He declarado más de las necesarias, para que podáis jugar con ellas si así os apetece.

Cuando PHP es usado como un programa de script, los argumentos (información que le pasamos desde la línea de comandos) vienen empaquetados en el array llamado $argv. Siempre, el elemento cero de este array es el nombre del programa. La variable $dir cuenta el número de argumentos, si es dos, significa que existe el argumento cero, ya descrito, y nos están proporcionando otro, que será la dirección del directorio a listar. En otras palabras, si me están proporcionando una dirección de directorio la incluyo con $argv[1], en caso contrario lo convierto en “.”, que significa literalmente «este directorio».

La siguiente variable $exec, contiene la orden find con los parámetros del directorio a listar $dir. Pero abundemos más en la sintaxis de ‘find [directorio] -maxdepth 1 -type f‘. Estamos indicando que queremos que encuentre en el directorio indicado con una profundidad (de subdirectorios) de 1, en otras palabras, sólo en ese directorio, prescindiendo de los subdirectorios que pudiera contener; los elementos tipo “f”: o sea, los ficheros. Para encontrar los subdirectorios prescindiendo de los archivos la orden sería ‘find [directorio] -maxdepth 1 -type d‘.

Con estas órdenes ya bastaría, pero quiero resaltar en negrita, sí, en el terminal de Linux, el nombre de los archivos. Realmente por eso realicé este script que os muestro.

Si el argumento que me han pasado es “-h” entiendo que quieren ver la ayuda, la muestro y salgo indicando error 0, que significa que no hubieron errores. Si el argumento es “-a” me están pidiendo el autor, lo muestro y salgo indicando error 0.

La orden exec en PHP ejecuta una orden de sistema operativo, tiene tres parámetros: el primero es la orden en sí. El segundo es un array con lo que nos devuelve el sistema tras la ejecución si hubiera tenido éxito. El tercero es el número de error que se produjo: cero si no lo hubo.

Por tanto si la variable $retval es cero, sé que tengo información que mostrar de la variable $output, porque no hubieron errores. A cada elemento lo someto a la función to_bold y lo muestro por pantalla.

Llevo cada valor de $output a to_bold(), y aquí lo que hago es descomponer cada elemento individual, buscando el carácter “/”, le doy la vuelta al string, porque así el nombre del archivo siempre estará a la izquierda de un carácter “/” (se me acaba de ocurrir que podría haber contado hacia atrás, pero eso es un lío). Lo retorno formateado y con las constantes que definimos, y muestro “salida sin errores”.

#!/usr/bin/env php

<?php
 /***
 * Muestra 'find . -maxdepth 1 -type f' 
 * Es decir: muestra exclusivamente los archivos de un directorio
 * 
 * @author: Pedro Ruiz Hidalgo, @pedroruizhidalg
 * @date: February 21 2017
 * 
 ***/
 define("RT","\n");
 define('TAB',"\t");
 define('RED',"\033[31m");
 define('BOLD',"\033[1m");
 define('NC',"\033[0m"); // ningún color
 define('NAME',$arg[0]);

 $dir = (count($argv)==2) ? $argv[1] : '.';
 $exec = "find $dir -maxdepth 1 -type f";
 
 if($dir=='-h')
 {
 echo RT.TAB.'help'.RT;
 echo RT.TAB.NAME.BOLD.' [DIRECTORIO]'.NC.RT.RT;
 exit(0);
 }

 if($dir=='-a')
 {
 echo RT.TAB.'Autor'.RT;
 echo RT.TAB.NAME.BOLD.' Pedro Ruiz Hidalgo (c) 2017'.NC.RT.RT;
 exit(0);
 }

 exec($exec,$output,$retval);

 if($retval==0)
 {
 foreach ($output as $value) {
 echo to_bold($value);
 }
 echo RT.BOLD.'Salida sin errores'.NC.RT;
 } else { 
 echo RT.RED."error resultado $retval".NC.RT;
 }

 function to_bold($value)
 {
 $pos="";
 $value=strrev($value);
 $pos=strpos($value,'/');
 $path=strrev(substr($value, $pos));
 return $path.$val=BOLD.strrev(substr($value, 0,$pos)).NC.RT;
 }

Ejecución

Guardar el archivo con el nombre “list.files”. Le damos permisos de ejecución con “chmod +x list.files”.

$ list.files 

./.directory
./tres60.tar.gz
./dlreves.tar.gz
./phpinfo.php
./bt.zip
./bootstrap.tar.gz

Salida sin errores
$

Debería mostraros algo así. Obviamente con vuestro contenido, 🙂

Epílogo

Espero y deseo que este artículo haya sido de utilidad. Es muy importante para la continuación de trabajos de calidad recibir algún tipo de feedback por parte de los lectores: es decir, responde con comentarios, evalúa la calidad del trabajo con el sistema de estrellas, comparte con tus redes sociales, da me gusta, marca el blog como favorito. Son pequeños gestos que ayudan a mantener el trabajo de creación.

 

 #aboutpedroruizhidalgo
[polldaddy poll=9120832]
♻ miotroblogsite ahorra papel