Funciones de orden superior

Tanto en matemáticas como en informática, las funciones de orden superior son aquellas que cumplen, al menos, una de estas condiciones:

  1. Esperan como argumento/s una o más funciones.
  2. Devuelven una función como resultado.

Ejemplos en matemáticas son la derivada y la antiderivada o función primitiva.

operador diferencial

El operador diferencial es una función de orden superior

Antiderivada

La antiderivada de una función f es una función F tal que F’ = f

En informática son la esencia de los lenguajes funcionales, pero también aparecen en lenguajes de otros paradigmas. Este es un ejemplo en el lenguaje Scheme en el que la función (f x) recibe un argumento y devuelve una función:

(define (f x)
  (lambda (y) (+ x y)))
(display ((f 3) 7))

Puede ejecutarse aquí para ver el resultado.

Cuando nació Javascript, a algunos programadores les pareció un lenguaje orientado a objetos fallido1, sobretodo porque, por razones comerciales, se le puso un nombre que lo asocia con Java. Desconozco si su creador estuvo muy de acuerdo con ese nombre pues, tal y como se diseño este lenguaje, da bastante juego a la programación funcional. En el siguiente ejemplo, el método filter() es una función de orden superior, pues espera recibir una función como parámetro:

function isPrime(x){
  if (x === 2) {
     return true;
  }
  let test = x%2 !== 0;
  let i = 3;
  stop = Math.floor(Math.sqrt(x)); // Raíz entera de x
  while (test && i <= stop) {
	  test = x%i !== 0;
	  i = i + 2;
  }
  return test;
}

const numbers = [47, 139, 137, 213, 2, 3, 45, 1515];
const primeNumbers = numbers.filter(isPrime);
console.log(primeNumbers);

Lo que este programa hace es filtrar la formación de números naturales “numbers“, dejando sólo los que sean primos en “primeNumbers“. Cada elemento de “numbers” será evaluado por la función “isPrime” mediante la criba de Eratóstenes. El lector puede ejecutarlo accediendo a la consola del navegador pulsando F12 y modificar el valor de “numbers” con los números (o el número) que quiera saber si son primos o no.

Este tipo de funciones están en prácticamente todos los lenguajes modernos, incluso en los que no se tuvo en cuenta el paradigma funcional en el momento de su creación. Es el caso de PHP, donde podemos encontrar una gran cantidad de funciones que esperan otra función, como es el caso de, por ejemplo, preg_replace_callback()2:

$capitalice = function($coincidencia) {
    return strtoupper($coincidencia[1]);
};

echo preg_replace_callback('~-([a-z])~', $capitalice, 'hola-mundo');

Además de usar las implementadas en funciones y métodos propios del lenguaje, también podemos crear las nuestras, de forma parecida a un lenguaje completamente funcional. En Javascript, la Wikipedia nos ofrece el siguiente ejemplo:

const twice = (f, v) => f(f(v));
const add3 = v => v + 3;

console.log(twice(add3, 7));

Lo mismo es posible en PHP:

$twice = function($f, $v) {
    return $f($f($v));
};

$f = function($v) {
    return $v + 3;
};

echo($twice($f, 7));

La programación funcional pretende tratar la programación como la evaluación de funciones matemáticas, paradigma muy diferente a la programación imperativa, basada en estados y en instrucciones que lo cambian. Tal vez las características funcionales que tienen algunos lenguajes puedan ayudarnos a introducirnos en un paradigma, el funcional, que nos exige una forma muy distinta de enfocar los problemas.


 

1 Todavía hoy en día, y a pesar de los cambios que ha sufrido en los últimos ECMA, sigue despertando las críticas de los programadores que, debido a su nombre, esperan que se comporte como un lenguaje completamente orientado a objetos, como Java, y se dan de bruces contra la realidad.

2 El parámetro que recibe la función contenida en $capitalize son las coincidencias que encuentre la expresión regular.

Cómo intercambiar el valor de dos variables enteras sin una intermedia

Cómo intercambiar el valor de dos variables enteras sin una intermedia es, en mi opinión, una mera curiosidad. Ahora bien, parece ser que en algunas entrevistas de trabajo aparece esta pregunta. Cuando se me ha pedido colaborar en el proceso de selección de un futuro compañero, no se me ha ocurrido incluir semejante pregunta en la prueba, pues no creo que esta sirva para apreciar la calidad de un programador. No obstante, si el presente artículo, además de presentar una anécdota, le sirve a alguien a superar una prueba, será un plus.

A continuación, voy a exponer dos métodos que, al usar Javascript para su implementación, el lector podrá ejecutarlos fácilmente presionando F12 para acceder a la consola.

Método matemático

Fácilmente lo podemos deducir con papel y lápiz:

var a = 3;
var b = 2;

a = a + b;
b = a - b; // Con el paso anterior y el actual es b = a + b - b
a = a - b; // a = a + b - a
console.log(a);
console.log(b);

Este método tiene una limitación con números muy grandes en los lenguajes que no manejan por si mismos el desbordamiento de enteros, que no es el caso de Javascript.

Método informático

Este es el mejor, consiste en usar el operador a nivel de bits XOR que, como se explica en el link, devuelve 1 si y solo si x e y son diferentes, mientras que en caso contrario retorna 0.

var x = 10;
var y = 3;

x = x^y;
y = x^y;
x = x^y;

console.log(x);
console.log(y);

Esta es la tabla de la verdad con los valores iniciales 10 y 3 para x e y, respectivamente:
Cómo intercambiar dos variables sin temporalAfirmé que es el mejor debido a que funcionará sin problemas en cualquier lenguaje, la única condición es que disponga de operadores a nivel de bits, algo que prácticamente todos cumplen.

Cuando las matemáticas se explican mal

En la EGB nos podrían haber explicado mejor las matemáticas, me di cuenta de esto años después, en Bachillerato, y a las malas. Si no es tu caso, me alegro por ti; en el nuestro tuvimos profesores que no tenían claro lo que explicaban, no se trataba de saber mucho (es sólo la EGB) sino de tenerlo muy claro. En mi opinión, en matemáticas es preferible avanzar poco pero con firmeza a avanzar mucho sin solidificar las bases, lo que conduce más pronto que tarde al desmoronamiento de lo que creíamos saber.

A continuación, expondré cómo me parece que hubiera sido mejor que explicaran algunos aspectos. Si eres profesor, espero que te pueda servir mi opinión (puedes dejarme la tuya en los comentarios); si eres alumno de la educación obligatoria, tal vez esto puedo ayudarte a clarificar algunos conceptos.

Los miembros de una ecuación no “pasan” al otro lado

Recuerdo que el profesor usaba expresiones como:

  • x pasa a dividir (o a multiplicar) al otro lado.
  • Tal número pasa a restar (o a sumar) al otro lado.

Como ejemplo de los errores a los que puede conducir pensar así, veamos la ecuación de la división entera:

D = d*q + r

Si pensamos que D “pasa a dividir al otro lado”, como el lado izquierdo de la igualdad queda vacío, podemos creer que esto es correcto:

0 = (d*q + r) / D

Si nos hubieran enseñado que, como ambos lados de la ecuación son iguales, la igualdad se mantendrá si operamos igual en ambos lados, pensaremos que vamos a dividir a ambos lados por D, con lo que llegaremos a una igualdad correcta:

D/D = (d*q + r) / D  → 1 = (d*q + r) / D

Segmentar la resolución de una ecuación

Otra zancadilla en nuestro aprendizaje nos la daba un profesor que usaba el punto y coma “;” para separar cada paso que ejecutaba para resolver la ecuación. Arrastré la coletilla hasta que en el Bachillerato, un compañero me preguntó por qué usaba un punto y coma en vez del signo igual. Tal vez sería más pedagógico usar el símbolo “implica que”:

x2 -9 = 0 ; x2 = 9 ; x = √3; x = ±3

x2 -9 = 0 ⇒ x2 = 9 ⇒ x = √3 ⇒ x = ±3

Lo que implica la igualdad

Deberían habernos dejado bien claro, incluso diría que machacado, que el hecho de que los dos lados de la ecuación sean iguales implica que seguirán siéndolo si se realiza la misma operación en ambos lados: elevar al cuadrado, al cubo, raíz cuadrada a ambos lados, etc. Cuando llega el momento, no está de más explicar que operaciones como las raíces pueden tener la limitación x ≥ 0 cuando operamos ecuaciones que las contienen, por ejemplo:

Estas condiciones son frecuentes en matemáticas: aparecen en los logaritmos y, pasada la educación obligatoria, vuelven a aparecer en el cálculo de límites, en las integrales, etc.

Potencia con exponente

En matemáticas se tiende a obviar los paréntesis que no son imprescindibles, esto nos puede inducir a creer que la siguiente igualdad es cierta, cuando no lo es:

En este caso, por la prioridad de los operadores, primero debe calcularse 34, 81, para finalmente operar 281. En cambio, mediante los paréntesis podemos indicar que la base no es 2 sino 23, es decir, la potencia de una potencia:

potencia correcta

La proporcionalidad

Acerca de las fracciones nos enseñaron prácticamente todo, pero viéndolo desde la distancia, me parece que se pasó a la ligera por el hecho de que el cociente entre dos magnitudes expresa cuánto de la magnitud del numerador corresponde a cada unidad de la magnitud del denominador. Después, en el Bachillerato, esto aparece de forma masiva en asignaturas como Química y Física:

  • F/m: La aceleración es la fuerza que actúa por unidad de masa.
  • F/q: La intensidad del campo eléctrico es la fuerza que actúa por unidad de carga eléctrica.
  • d = m/V: La densidad es la masa de un objeto por unidad de volumen.

En el cotidiano acto de la compra tenían nuestros profesores un buen ejemplo, si por ejemplo un cartel anuncia que la malla de 6 Kg de naranjas cuesta 3’84€ y queremos saber cuánto cuesta el kilogramo, tendremos que poner el precio en el numerador y el peso en el denominador, pues deseamos conocer el precio en función del peso.

Aunque el ejemplo de la compra pueda parecer muy básico, el mismo concepto, la proporcionalidad, permite hallar la solución a problemas aparentemente más complejos, como el siguiente que nos servirá a modo de ejemplo. Tenemos un tramo de fibra óptica de 300 metros por el que se desplaza un haz de luz (línea negra), “rebotando” por reflexión total interna.

fibra óptica

Esquema del tramo de fibra óptica

Si sólo sabemos el valor de ϴc como la luz no se desplaza en línea recta sino en zigzag, aparentemente no podemos calcular la distancia real que recorre la luz, pero gracias a la proporcionalidad directa y algo de trigonometría podemos encontrar solución.

trigonometria haz de luz

El seno de un ángulo es el cateto opuesto entre la hipotenusa

Vemos que existe una proporcionalidad directa entre X y L, pues sen(ϴc) es una constante. Por lo tanto, sea e la distancia real recorrida por luz, sabemos que la siguiente igualdad, que nos permite calcular la distancia realmente recorrida en zigzag, es cierta:

En definitiva, creo que una mayor rigurosidad en la exposición de los conceptos básicos nos hubiera ayudado a aposentar algunos conceptos básicos en matemáticas; una asignatura difícil, incluso para enseñarla.

Decimales del número e por Taylor

Tanto Jhon von Neumann como Steve Wozniack hicieron el ejercicio de encontrar miles de decimales del número e, en el ENIAC (uno de los primeros ordenadores de propósito general) y en un Apple II, respectivamente. Si personas de tan elevado tamaño intelectual consideraron oportuno hacerlo, ¿quién soy yo para contrariarlos? Así que, salvando las distancias, me he decidido a hacerlo.

El método empleado han sido las series de Taylor. Para el mismo, se requiere calcular el factorial, la siguiente función recursiva lo calcula para el número recibido como parámetro:

function factorial(a) {
  if (a === 0) {
      return 1;
  }else{
      return a * factorial(a - 1);
  }
}

El siguiente código Javascript calcula, a partir del polinomio de Taylor1 de grado 20 en torno al punto a=0, es decir, e1, unos cuantos decimales:

function factorial(a) {
  if (a === 0) {
      return 1;
  }else{
      return a * factorial(a - 1);
  }
}

var e = 1;

for (i = 1; i <= 19; i++) {
   e = e + 1/factorial(i);
}
console.log(e);

El lector puede copiar el código y ejecutarlo en el mismo navegador con el que está leyendo este artículo, presionando F12 y accediendo a la consola:

Decimales de e en Javascript por Taylor

Decimales de e en Javascript por Taylor. Ejecutado en Firefox.

Por culpa del uso de la coma flotante que hace Javascript (ya incluido en el microprocesador), no podemos sacar más decimales, pues el resultado será redondeado al que vemos en la imagen. Para salvar este inconveniente, en PHP existe la librería BC Math, que nos permite trabajar con números de – casi – cualquier tamaño y precisión. Para que después digan que es un lenguaje de juguete… Éste es el código:

<?php

function factorial($a) {
  if ($a === 0) {
      return 1;
  }else{
      return bcmul($a, factorial($a - 1), 3000);
  }
}

$e = '2';

for ($i = 2; $i <= 1000; $i++) {
   $e = bcadd($e, bcdiv('1', factorial($i), 3000), 3000);
}
echo ($e);

Con el que se obtienen 2572 dígitos correctos:

2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901157383418793070215408914993488416750924476146066808226480016847741185374234544243710753907774499206955170276183860626133138458300075204493382656029760673711320070932870912744374704723069697720931014169283681902551510865746377211125238978442505695369677078544996996794686445490598793163688923009879312773617821542499922957635148220826989519366803318252886939849646510582093923982948879332036250944311730123819706841614039701983767932068328237646480429531180232878250981945581530175671736133206981125099618188159304169035159888851934580727386673858942287922849989208680582574927961048419844436346324496848756023362482704197862320900216099023530436994184914631409343173814364054625315209618369088870701676839642437814059271456354906130310720851038375051011574770417189861068739696552126715468895703503540212340784981933432106817012100562788023519303322474501585390473041995777709350366041699732972508868769664035557071622684471625607988265178713419512466520103059212366771943252786753985589448969709640975459185695638023637016211204774272283648961342251644507818244235294863637214174023889344124796357437026375529444833799801612549227850925778256209262264832627793338656648162772516401910590049164499828931505660472580277863186415519565324425869829469593080191529872117255634754639644791014590409058629849679128740687050489585867174798546677575732056812884592054133405392200011378630094556068816674001698420558040336379537645203040243225661352783695117788386387443966253224985065499588623428189970773327617178392803494650143455889707194258639877275471096295374152111513683506275260232648472870392076431005958411661205452970302364725492966693811513732275364509888903136020572481765851180630364428123149655070475102544650117272115551948668508003685322818315219600373562527944951582841882947876108526398139559900673764829224437528718462457803619298197139914756448826260390338144182326251509748279877799643730899703888677822713836057729788241256119071766394650706330452795466185509666618566470971134447401607046262156807174818778443714369882185596709591025968620023537185887485696522000503117343920732113908032936344797273559552773490717837934216370120500545132638354400018632399149070547977805669785335804896690629511943247309958765523681285904138324116072260299833053537087613893963917795745401613722361878936526053815584158718692553860616477983402543512843961294603529133259

Aquí está el link que ejecuta este código:

https://www.victoriglesias.net/e.php

Al seguir el link, el lector con interés en el tema descubrirá que proporciona más decimales, pero, como dije, sólo los primeros 2572 son correctos. Supongamos que sabemos que e está por debajo de 3, pero no podemos concretar más, el error, por el residuo del teorema de Taylor, sería 3/(i + 1)!, es decir:

+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000744805637342692...

Por cierto, no por acotar mejor e, por ejemplo 2’8, dejaríamos de obtener menos posiciones a 0 hasta obtener los primeros decimales del error. 2’8/(i + 1)! es:

+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000695151928186513...

Por lo tanto, aunque acotemos con más precisión e, la fórmula del residuo nos sigue asegurando que hemos calculado correctamente la misma cantidad de decimales.

Si parecen insuficientes y se desea mayor precisión, bastará con incrementar el tope de la variable i del bucle a más de 1000. Eso sí, si nos tomamos este cálculo en serio, sería aconsejable optimizar previamente la función recursiva.

En definitiva, aunque me quedé muy lejos del récord mundial ;-), fue entretenido hacerlo y espero que al lector le parezca interesante también o, por lo menos, curioso.


1 Se llama serie de Maclaurin el caso concreto de Taylor a=0

¿Por qué lo llaman logaritmo neperiano cuando quieren decir natural?

Normalmente denominamos “neperiano” al logaritmo de base e, pero viendo un vídeo en inglés escuché que se referían al mismo como “natural”, entonces me puse a indagar cual de las dos formas es correcta. El resultado fue que “natural” sería más correcto, pero entonces, ¿por qué lo llamamos neperiano? Voy a explicar en esta breve entrada lo que averigüé.

Leyenda de un libro de matemáticas de 3º de BUP

Leyenda de mi libro (I de II) de matemáticas de 3º de BUP

John Napier, un matemático escocés que vivió entre 1550 y 1617, fue el primero en definir los logaritmos. Su trabajo, como era lo usual en la época, lo publicó en latín, y fue otro matemático quien, tiempo después, traduciría la obra al inglés. En una de las ediciones, se incluyó un apéndice con una tabla de logaritmos, y en la misma aparecen algunos valores que se obtienen usando la base 2.718, pero sin hacer ninguna mención en especial a la misma. Esta base, por cierto, no aparece en la obra original de Napier.

Logarithmorum, de John Napier

Las largas noches de invierno en el norte de Europa dan para mucho.

No obstante, en aquel entonces, el número e todavía no había sido formalmente definido. Probablemente, el autor de esta tabla, que se cree que fue William Oughtred, tuvo nociones acerca de e, al igual que otros matemáticos de la época, pero al descubrimiento y su formalización todavía le faltaba entorno a un siglo. En todo caso, si bien a John Napier se le reconoce el mérito del logaritmo como su gran aportación a las matemáticas, no sería justo otorgarle el mérito de uno de los números más importantes.

En definitiva, parece que los anglosajones están más acertados que nosotros a la hora de llamar “natural” al logaritmo en base e y que somos nosotros quienes andamos algo equivocados al otorgarle a John Napier más méritos de los que le corresponden.

Uso avanzado de Find y Grep

Durante todos mis años de desarrollado LAMP, han habido una serie de comandos UNIX que me han sido muy útiles. En este artículo voy a compartir unos ejemplos de su uso que van más allá de su empleo básico, con el objetivo de que sirva de ayuda para otros desarrolladores. En esta ocasión voy a centrarme en find y grep, más adelante me gustaría ampliar este artículo con otros comandos que facilitan la vida al programador y al usuario de Unix / Linux en general.

Entrada, salida y su redireccionamiento

Antes de empezar, no estaría de más, para una mayor claridad de los ejemplos, explicar que en Unix el standard output (salida) e input (entrada) es la consola. Debemos tenerlo en cuenta para redireccionar tanto la salida como la entrada de datos de las órdenes mediante pipelines ( < > | )

find y grep

Grep es una poderosa herramienta que nos permite encontrar coincidencias dentro de un fichero o de un conjunto de ellos, gran parte de sus “superpoderes” emanan de las expresiones regulares. A continuación, veamos unos ejemplos de su uso para búsquedas no muy elementales:

– En primer lugar, con grep hay que escapar los caracteres especiales:

grep "regex|regex not" borrame.txt  => grep "regex\|regex not" borrame.txt

– Si no se quiere escaparlos para que no los entienda como parte de la cadena buscada, debemos usar la opcion -E o bien egrep:

grep -E "regex|regex not" borrame.txt

egrep "regex|regex not" borrame.txt

– Para buscar una cadena de texto en ficheros filtrados recursivamente:

grep -r --include="*.php" "yorkshiresConfig.ini" * > resultados.txt

Esta orden buscaría recursivamente, a través de todos los subdirectorios, la cadena “yorkshiresConfig.ini” en todos los ficheros con extensión php.

El nombre de la orden find ya nos dice todo acerca de su función. Se vuelve realmente poderosa cuando se combina con otras órdenes. He aquí algunos ejemplos:

– Para borrar ficheros resultantes de una búsqueda de cierto tipo de ficheros, con los subdirectorios incluidos:

find -name '*.po' -exec rm -i {} \;

– Para borrar todos los ficheros que tengan más de 50 días:

find /compartido/backups/pro/auto/bd/* -mtime +50 -exec rm {} \;

Como fácilmente podemos acabar borrando lo que no deseábamos, con la opción -i el programa rm pedirá confirmación por cada fichero.

– Para moverlos a otro directorio:

find -name '*.po' -exec mv {} ./poBackups \;

– También podemos renombrar masivamente ficheros, el siguiente comando busca recursivamente todos los ficheros “.po” y los renombra a “.po.bak”:

find -name '*.po' | sed 's/\(.*\).po$/mv "&" "\1.po.bak"/' | sh

Si en vez de “find -name ‘*.po”‘ usáramos “ls -d *.po” serían sólo los directorios del directorio actual.

Busca en el directorio acutal y en los subdirectorios todos los ficheros con la extensión php que contengan la cadena “Possible reason: your host may have disabled the mail“:

find -name '*.php' -exec grep 'Possible reason: your host may have disabled the mail' {} \;

Cuando el listado de resultados es demasiado grande como para manejarlo cómodamente en el terminal, podemos redireccionar el resultado con una pipe desde el standard output a un fichero:

find -name '*.php' -exec grep 'Possible reason: your host may have disabled the mail' {} \; > results.txt

Si de cada fichero encontrado queremos saber su ruta exacta, debemos añadir “-print” al final:

find -name '*.php' -exec grep 'Possible reason: your host may have disabled the mail' {} \; -print

La orden find también nos permite buscar por fechas:

– Encontrar ficheros modificados en el último día:

find -ctime -1 -type f

– Si en vez de “f” usamos “d“, le indicamos que trabaje sólo con directorios:

find -ctime -1 -type d

– Encontrar ficheros más recientes que main.css:

find -newer main.css

Contar el número de ficheros de un directorio y subdirectorios:

find . -type f | wc -l

ls y mv al rescate

A veces, las herramientas más básicas son las adecuadas. Esto es especialmente cierto en UNIX, pues en su tradición está la filosofía de disponer de muchas pequeñas herramientas para tareas muy concretas, permitiendo al usuario combinarlas para conseguir objetivos más complejos.

–  Para contar los elementos del directorio actual podemos usar la orden wc (Word Count), en combinación con ls. El parámetro -l indica que cuente líneas en vez de palabras, por lo tanto, contará el número de líneas que devuelve ls:

ls -1 | wc -l

– Listar sólo los directorios, sin los ficheros, del directorio actual:

ls -d */

– Listar sólo los directorios de un subdirectorio:

ls -d Proyectos/*/

– Mover sólo los ficheros ocultos de un directorio (origen) a otro (dest):

mv origen/{*,.*} dest/