2.4.2. Interpretaciones en línea

La labor del intérprete de comandos no se limita a proporcionar el medio para que podamos ejecutar una orden pasando los argumentos adecuados. Antes de ello, el intérprete analiza la línea y realiza (o no) una serie de transformaciones.

El objetivo de este epígrafe es describir cuáles son las interpretaciones y sustituciones que hace la shell antes de pasar definitivamente los argumentos al comando invocado.

No obstante, antes de empezar es conveniente saber cómo se puede evitar que bash no interprete un carácter especial, permitiendo así pasárselo literalmente a la orden. Hay tres métodos, que llamaremos de protección, porque protegen al carácter de ser interpretado por bash:

  1. Escapar el carácter, que consiste en precederlo de la barra invertida (\). Por ejemplo, la exclamación (!) tiene un significado especial, sin embargo:

    $ echo \!
    !
    

    Si se escapa no se hará interpretación alguna.

  2. Encerrar el carácter (o la expresión en la que se encuentra tal carácter) dentro de comillas dobles:

    $ echo "*"
    *
    
  3. Encerrar el carácter (o la expresión en la que se encuentra tal carácter) dentro de comillas simples:

    $ echo '!'
    !
    

No obstante, estos tres métodos no son equivalentes, y hay interpretaciones que dejan de hacerse usando algún método, pero no otro. En cada caso, particular indicaremos qué métodos son efectivos.

2.4.2.1. Espaciado

Los caracteres de espaciado (el espacio normalmente, pero también la tabulación1) sirven a bash para separar argumentos. Por ese motivo la orden:

$ cat x y

Le pasa a cat el argumento x y el argumento y. Para el caso de estos caracteres de espaciado cualquiera de los tres métodos de protección sirve para impedir la interpretación. Por tanto:

$ cat x\ y

Intentará mostrar el contenido de un único fichero llamado «x y«.

2.4.2.2. Historial

bash almacena las ordenes que vamos introduciendo en la línea de comandos a fin de poder recuperarlas posteriormente.

history

Muestra el historial de comandos:

$ history

La manera más sencilla de recuperar instrucciones anteriores es usar la flecha arriba. Sin embargo, hay otros mecanismos que usan el carácter especial de exclamación (!). Los más habituales son los siguientes:

  1. Volver a ejecutar la última orden:

    $ !!
    
  2. Ejecutar la orden 25º (history muestra los comandos numerados):

    $ !25
    
  3. Ejecutar la penúltima orden (o sea, la segunda empezando por el final):

    $ !-2
    
  4. Ejecutar la última orden que empezaba por se:

    $ !se
    

Las expresiones anteriores ejecutan las órdenes completas, pero se pueden añadir dos puntos y, a continuación, expresar cuáles son los argumentos que se quieren repetir (el argumento 0 es el nombre del comando). Supongamos que ejecutamos lo siguiente:

$ cat fichero1 fichero2 fichero3

Ahora analicemos las posibilidades:

  1. Un único número indica que se quiere repetir ese argumento:

    $ more !!:1
    

    Esto equivale a more fichero1.

  2. Un rango de números x-y indica que se quiere repetir desde el argumento x al argumento y:

    $ !!:0-2
    

    equivale a cat fichero1 fichero2.

  3. Un rango de números x- indica que se quiere repetir desde el argumento x hasta el último:

    $ cat !!:2-
    

    equivale a cat fichero2 fichero3

  4. Un rango de números -x indica que se quiere repetir hasta el argumento x:

    $ !!:-2
    

    equivale a cat fichero1 fichero2.

Para proteger la exclamación se puede tanto escapar como incluirla dentro de comillas simples, pero no dobles.

2.4.2.3. Comodines

Los comodines permiten hacer sustituciones a partir del nombre de los ficheros. Los tres métodos de protección impiden que bash los interprete. Son tres:

?

Representa cualquier carácter. Por ejemplo:

$ ls -d /s??
/srv /sys

En el directorio raíz sólo hay dos ficheros (directorios en este caso) que empiecen por s y que tengan dos caracteres más. Consecuentemente, eso es lo que obtenemos.

Advertencia

Es muy importante tener presente que las interpretaciones las hace bash, no el comando (en este caso ls). En el caso del ejemplo, ls ve tres argumentos: la opción -d el directorio /srv y el directorio /sys sin tener conciencia de que realmente no se llegó a escribir esto.

*

Representa cero o más caracteres. Por ejemplo:

$ echo /s*
/sbin  /srv  /sys

En este caso, dado que puede haber cualquier cantidad de caracteres, también /sbin cumple con el patrón.

[…]

Permite indicar un conjunto de caracteres, uno de los cuales puede encontrarse en el nombre del fichero:

$ ls -d /s[by]*
/sbin /sys

En este caso no aparece /srv porque el segundo carácter sólo puede ser una b o una y. Si a la relación de caracteres se antepone un ^, entonces la expresión significa cualquier carácter que no sea uno de los indicados en ella:

$ ls -d /s[^by]*
/srv

Se admite también la forma [b-e] para indicar que son válidos todos los caracteres entre la b y la e, esto es, b, c, d y e.

Nota

Cuando no hay ficheros que concuerden en absoluto con la expresión que usa comodines, bash no realiza ninguna interpretación2:

$ ls /?
ls: no se puede acceder a '/?': No existe el fichero o el directorio

Como no hay ningún fichero en el directorio raíz que sólo contenga una letra, bash pasa el argumento sin interpretar, razón por la que (como se puede observar en el mensaje de error) ls ve la cadena /?.

2.4.2.4. Expandibles

También existe en bash (pero no en dash) la llamada expansión con llaves que opera de la siguiente forma:

$ echo pre{11,22,33}su
pre11su pre22su pre33su

es decir, se forman todas las cadenas resultantes de juntar el prefijo (en este caso, pre) con cada uno de los miembros de la expresión encerrada entre llaves y con el sufijo (en el ejemplo, su). Tanto el prefijo como el sufijo son opcionales. A diferencia de la expansión con corchetes, en este caso, las cadenas no están asociadas a nombres de ficheros con lo que la expansión se producirá siempre.

Otra expansión con llaves se expresa con dos caracteres separados por dos puntos:

$ echo {X..b}
X Y Z [  ] ^ _ ` a b

En este caso, la expresión se expande a todos los caracteres ascii que hay entre el primero y el segundo. También puede indicarse un paso:

$ echo {X..b..2}
X Z  ^ ` b

Con lo que bash expandirá, pero saltando de 2 en 2. Si en vez de caracteres se usan números, bash expandirá a todos los números que haya entre uno y otro (también se puede indicar un paso):

$ echo {1..12}
1 2 3 4 5 6 7 8 9 10 11 12

Nota

Una vez que bash realiza la expansión con llaves, vuelve a probar si las cadenas resultantes son interpretables o no, sea con una nueva expansión con llaves o con cualquier otro tipo de expansión. Por ejemplo:

$ ls -d /{s*,li*}
/lib  /lib64  /sbin  /srv  /sys

Como en el caso de los comodines, los tres métodos de protección son efectivos.

2.4.2.5. Expansiones extendidas

bash (y sólo bash) realiza también las expansiones extendidas cuando está habilitada la opción extglob (que lo está por defecto):

$ shopt extglob
extglob         on

Esto posibilita la expresión de varios patrones para expandir rutas:

?(lista-patrones)

La ruta contiene los patrones una o ninguna vez:

$ ls *?(.tar).gz
+(lista-patrones)

La ruta contiene los patrones una o más veces:

$ ls *([aeiou]).txt  # El nombre sólo contiene vocales.
*(lista-patrones)

La ruta contiene los patrones ninguna o más veces.

@(lista-patrones)

La ruta contiene uno de los patrones:

$ ls *.@(jpg|png)

Cuando se facilita más de un patrón, se separan con una tubería «|» (también en los restantes casos, aunque el ejemplo no lo refleje).

!(lista-patrones)

La ruta no contiene ninguno de los patrones:

$ ls !(*.jpg)  # Ficheros que no acaban en jpg.

2.4.2.6. Subshells

Ya se ha dicho que en bash los paréntesis generan una subshell en la que se ejecutan las órdenes encerradas dentro. Ahora bien, si a los paréntesis se antepone el símbolo del dólar, entonces :program:` sustituirá la expresión entre paréntesis por la salida en pantalla que genera. Para entender esto, supongamos que tenemos un usuario pepe, que pertenece a una serie de grupos; y queremos crear un usuario llamado maría que queremos que pertenezca también a esos mismos grupos. Ya sabemos cómo obtener la lista de grupos a los que pertenece pepe:

# id -Gn pepe
pepe audio video plugdev lpadmin

Por tanto, la creación de maria consistiría en lo siguiente:

$ adduser maria
[...]
$ usermod maria -aG pepe,audio,video,plugdev,lpadmin

Lo cual implica el engorro de tener que ir copiando lo que nos indicó el primer comando id. Ahora bien, más adelante aprenderemos que podemos modificar la salida que obtenemos:

$ id -Gn pepe | tr ' ' ','
pepe,audio,video,plugdev,lpadmin

Y esta es justamente lo que necesitamos como argumento de -G. Como hemos dicho que anteponer un dólar a la expresión de la subshell, sustituye ésta por su salida, resulta que el usermod podemos hacerlo del siguiente modo:

·$ usermod maria -aG $(id -Gn pepe | tr ' ' ',')

sin necesidad de estar copiando y pegando.

Nota

La expresión $(...) también puede expresarse con apóstrofes invertidos:

$  usermod maria -aG `id -Gn pepe | tr ' ' ','`

Sólo la comillas dobles no son efectivas para proteger esta interpretación. Téngase en cuenta que si se quiere proteger con el símbolo de escapa, se deben proteger el dólar y los paréntesis de apertura y cierre, o sea, \$\(id ... \).

Nota

En bash la expresión $(cat fichero) puede sustituirse por $(< fichero).

2.4.2.7. Variables

El entorno que proporciona la shell tiene definidas una serie de variables que rigen el comportamiento de algunos aspectos del intérprete de comandos. También pueden definirse variables propias, pero esto cobra sentido más bien cuando escribimos nuestros propios scripts y no cuando usamos de forma interactiva el sistema.

set

Usado sin argumentos, lista las variables definidas:

$ set
[... Listado de variables y funciones ...]

Cuando sepamos que es una tubería sabremos cómo poder inspeccionar mejor la salida de este comando. En realidad, set permite hacer más cosas si se le añaden argumentos. Por ejemplo, esto hace que bash nos informe de la orden que está ejecutando:

$ set -v
$ ls -w80 /
ls -w80 /
bin   home            lib64       opt   sbin  usr
boot  initrd.img      lost+found  proc  srv   var
dev   initrd.img.old  media       root  sys   vmlinuz
etc   lib             mnt         run   tmp   vmlinuz.old

Lo cual no tiene mucho interés en el entorno interactivo. pero puede ser útil si estamos depurando un script y queremos saber con qué orden falla. Para deshacer el cambio basta con hacer set +v.

Hay otras muchas opciones (-f, por ejemplo, deshabilita comodines y expansiones) que pueden verse en la página de manual de bash (o mejor, de builtins), ya que set es un comando interno.

env

Sin argumentos, lista las variables de entorno definidas. Las variables de entorno son aquellas heredables por un hijo del proceso actual. Por ejemplo:

$ sh -c 'echo valor=$HOME'
valor=/home/usuario
$ aa="No soy de entorno"
$ sh -c 'echo valor=$aa'
valor=

HOME es una variable de entorno. Por tanto, si se pregunta por su valor en una shell hija, también existirá. En cambio, aa es una variable que definimos en la shell actual, pero no es de ambiente3 (o sea, heredable), por tanto, en la shell hija no existirá. Como ambas son variables, set mostrará el valor de ambas; env, en cambio, sólo mostrará HOME.

Para obtener el valor de una variable, hay que anteponer a su nombre el símbolo del dolar:

$ echo $HOME
/home/usuario

También es posible rodear el nombre con llaves para indicarle a bash dónde empieza y acaba el nombre de la variable:

$ echo x${HOME}x
x/home/usuario/x

ya que si escribiéramos $HOMEx, la shell pensaría que el nombre de la variable es HOMEx. Si la variable no existe, se sustituye por la cadena vacía:

$ echo x$HOMEx
x

La interpretación del dólar puede protegerse escapándolo o con comillas simples, pero no con las dobles:

$ echo '${HOME}' -- \$\{HOME\} -- "${HOME}"
${HOME} -- ${HOME} -- /home/usuario

2.4.2.7.1. Variables predefinidas

Hay muchas variables de entorno disponibles. Algunas interesantes son:

$$

Devuelve el pid del proceso actual. Si estamos en una sesión interactiva, devolverá el pid de la sesión de bash.

$?

Devuelve el resultado del último programa ejecutado. Los programas para informar de si han tenido éxito o no, devuelven a su entorno un byte, que valdrá 0 si tuvo éxito, u otro valor distinto, si no lo tuvo. Por este motivo:

$ true
$ echo $?
0
$ false
$ echo $?
1
$!

Almacena el pid del último programa ejecutado en el background. Véase el epígrafe sobre gestión de procesos.

$EDITOR

Determina cuál es el editor predeterminado que usarán programas como crontab o visudo.

En debian, hay tres mecanismos4 para que los programas que hacen uso de la edición, escojan el editor. Por orden de prioridad son:

  1. A través de las alternativas de debian.

  2. Mediante la configuración del programa sensible-editor.

  3. Leyendo el valor de la variable EDITOR.

$HISTFILE

Define cuál es el fichero en el que se almacenará el historial de bash. Habitualmente su valor es ~/.bash_history.

$HOME

Devuelve el directorio personal del usuario.

$HOSTNAME

Devuelve el nombre de la máquina. Puede usarse también el comando hostname.

IFS

Su nombre es el acrónimo de Separador Interno de Campos. y tiene importancia en algunas operaciones de la shell.

Ver también

Consulte la explicación de la orden read y la discusión sobre los argumentos de un programa para ver algunos ejemplo del usuo de este variable.

$OLDPWD

Devuelve el nombre del directorio anterior al actual. Es útil si se quiere volver a él:

$ cd $OLDPWD
$PATH

Lista los directorios que el sistema considera que contienen ejecutables. Se separa un directorio del siguiente por dos puntos (:):

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Esto permite invocar órdenes sin tener que indicar la ruta completa. Por este motivo es posible escribir:

$ cp fichero1 fichero2

Sin necesidad de escribir:

$ /bin/cp fichero1 fichero2

En el primer caso, el intérprete recorre la lista de directorios que contiene la variable de izquierda a derecha, analizando si tal ejecutable está o no. Al encontrarlo lo ejecuta; si no lo encuentra en ninguno de los directorios, genera un error:

$ PATH=""  # <---- Ahora PATH está vacío y bash no busca.
$ cp fichero1 fichero2
-bash: cp: No existe el fichero o el directorio

Nota

Obsérvese que el directorio actual no se encuentra en la lista de directorios. Por ese motivo, para ejecutar un programa que se encuentra en el directorio de trabajo es necesario:

$ ./mi_script.sh
$PS1

Define el prompt de usuario.

$PWD

Devuelve el directorio actual de trabajo, accesible también a través del comando pwd.

2.4.2.7.2. Variables de usuario

Cualquier usuario puede definir sus propias variables simplemente dándoles valor:

$ MIVAR=4
$ echo ${MIVAR}
4

Por supuesto, esto también es aplicable a las variables vistas en el apartado anterior:

$ PATH="~/bin/:$PATH"

Salvo este último caso de redefinición de variables ya existentes, no suele tener gran utilidad en consolas interactivas, pero cobra capital importancia cuando se escriben scripts. Al tratarlos, profundizaremos en ellas.

No obstante, debe significarse que, cuando se definen variables, ha de tenerse en cuenta que estas, en principio, sólo existen dentro de la propia sesión de bash, y no las heredan los programas hijo. Por ejemplo:

$ echo MIVAR=4
$ echo %${MIVAR}%
%4%
$ bash -c 'echo %${MIVAR}%'
%%

Para que convertirlas en variables de entorno es necesario exportarlas.

export

Permite convertir una variable en variable de entorno, es decir, hacerla heredable por los procesos hijo. La sintaxis es:

export [-f|-n] nombre[=valor] [nombre2=valor2 ...]

Cuando la variable se exporta puede ya tener definido un valor. En ese caso, basta con indicar el nombre de la variable:

$ MIVAR=4
$ export MIVAR

Pero también puede hacerse la asignación a la vez que se realiza la exportación:

$ export MIVAR=4

Si se exportó la variable, entonces ya estará disponible en el entorno de cualquier programa hijo:

$ bash -c 'echo %${MIVAR}%'
%4%

Si se desea desmarcar la variable como exportable, basta con usar la opción -n:

$ export -n MIVAR
$ bash -c 'echo %${MIVAR}%'
%%

Por último, es posible mostrar todas las variables exportadas usando la opción -p:

$ export -p
[... Lista de variables y funciones exportables ..]

Nota

La opción -f sire para exportar funciones en vez de variable (sólo en bash, ya que dash no puede exportar funciones)

Otra posibilidad que proporciona la shell es pasar la definición de una variable a un programa hijo. Esto se hace anteponiendo la asignación de la variable al comando:

$ A=1 bash -c 'echo $A'
1

Pueden, asimismo, realizarse varias asignaciones:

$ A=1 B=2 bash -c 'echo $A -- $B'
1 -- 2

2.4.2.8. Evaluación aritmética

Para la realización de operaciones, pueden recurrirse a la evaluación aritmética usando la sintaxis:

$(( ... ))

Entre paréntesis debemos colocar una expresión tal y como se escribiría en en lenguaje C:

$ SUMA=$((1+2))
$ echo $SUMA
3

Las comillas dobles permiten a la shell interpretar la expresión; los otros dos mecanismos lo evitan:

$ echo "La suma de 1 y 2 es $((1+2))"
La suma de 1 y 2 es 3

Además de estas operaciones, bash permite con la sintaxis de los dos paréntesis, otras dos operaciones:

  1. Asignar valor a variables (lo cual sólo tiene sentido si hay involucradas operaciones aritméticas, ya que de otro modo basta con usar el método general para dar valor a la variable):

    $ ((A = 1+2))
    $ echo $A
    3
    $ ((A++))
    $ echo $A
    4
    

    Nota

    Obviamente, esta forma de asignación sólo tiene sentido si incluimos alguna operación aritmética; de lo contrario, es más sencillo usar directamente el método general de asignación.

  2. Hacer una evaluación lógica:

    $ ((A == 3)) || echo "A no vale 3"
    A no vale 3.
    

    Nota

    Al tratar la programación, ya veremos cómo realizar esto mismo con test.

2.4.2.9. Alias

Los alias son palabras que permiten acortar la digitalización de un comando. Habitualmente se usan para ejecutar siempre ciertos comandos con una o varias opciones predeterminadas. En realidad, lo más probable es que existan ya definidos en el sistema. Uno que viene en debian para el usuario sin privilegios es este:

$ alias ls
alias ls='ls --color=auto -F'

O sea, que cuando ejecutamos ls, en realidad, estamos ejecutando ls --color=auto -F. Por esta razón, la salida sale coloreada. Cuando se quiere ejecutar el comando a secas y no el alias, es necesario anteponer al comando la barra invertida:

$ \ls

o bien usar la orden interna command, que tiene el mismo efecto:

$ command ls

Esto mostrará una salida sin colorear ni decorar los nombres, o sea, la ejecución pelada de ls.

Hemos visto ya cómo consultar el alias definido para un cierto comando. Es posible que se muestren todos, ejecutando alias sin argumentos:

$ alias
alias ls='ls --color=auto -F'
alias tar='tar --no-overwrite-dir'
alias scp='scp -p'
alias tmux='tmux -2 attach || tmux -2 new-session'

Para definir nuevos alias, basta con usar la sintaxis que ha aparecido en la salida. Por ejemplo, cp, mv y rm es muy recomendable usarlos añadiendo la opción -i. Por tanto, es muy útil añadir los alias:

$ alias mv='mv -i'
$ alias cp='cp -i'
$ alias rm='rm -i'

Sin embargo, todas estas definiciones sólo tienen validez hasta que acabe la sesión. Si queremos hacer cambios permanentes es necesario escribirlos en ficheros que se lean al iniciar las sesiones. De esto trataremos en el siguiente apartado.

2.4.2.10. ¿Cómo definir variables de entorno y alias?

La respuesta es sencilla: escribiendo la definición de las variables o los alias en los directorios que bash lee al ejecutarse para abrir sesión. Estos fichero son:

/etc/profile

Sea cual sea el usuario que abre sesión. se lee este fichero. Por tanto, si se desea hacer un cambio que afecte a todos los usuarios, puede escribirse aquí. No obstante, este fichero llama a su vez a /etc/bash.bashrc por lo que deberíamos ver si nuestro nuestro cambio, será desecho después.

Sin embargo, lo mejor es escribir nuestro código en un nuevo fichero dentro de /etc/profile.d/, para no modificar los ficheros de la propia distribución. El fichero debe tener extensión .sh.

~/.bash_profile, ~/.bash_login, ~/.profile

Los tres ficheros son, obviamente, particulares de cada usuario. Después de leer los ficheros anteriores, bash busca por el orden especificado estos tres ficheros y en cuanto encuentra uno, ese lee. Lo habitual es que nos topemos con que existe ~/.profile, que a su vez lee el fichero que se cita a continuación.

~/.bashrc

Es el fichero que lee bash cuando la sesión es interactiva, pero no de login. La mayor parte de las sesiones interactivas son de login, pero no todas. Por ejemplo, no son de login las sesiones que se abren con el comando su si no se usa la opción -.

Por tanto, si quisiéramos que para nuestro usuario particular los comandos cp, mv y rm preguntaran antes de hacer una acción destructiva, podríamos incluir las tres líneas de alias mediante la edición del fichero ~/.bashrc. Ahora bien, añadir indiscriminadamente líneas a este fichero no es buena idea, porque se acabará convirtiendo en un monstruito con configuración predeterminada muy diversa. Es mejor en cambio, crear un directorio de configuraciones ~/.bashrc.d e incluir dentro de él la configuración modular. Para ello debe hacerse uso del comando interno:

source

Lee en la shell actual una serie de órdenes almacenadas en un fichero. Su sintaxis es:

source <fichero>

En vez de usar la palabra source puede escribirse simplemente un punto (.). De hecho, el punto es lo único que entiende dash.

Sabido esto, la forma de intergrar el directorio de configuraciones dentro de la configuración es añadir a ~/.bashrc las siguientes líneas:

if [ -d ~/.bashrc.d ]; then
   for conf in ~/.bashrc.d/*.sh; do
      . "$conf"
   done
fi

que provocará que se interpreten todas las instrucciones incluidas en ficheros de ese directorio cuya extensión sea .sh. Así pues:

$ mkdir ~/.bashrc.d
$ cat > ~/,bashrc.d/10-aliases.sh
alias mv='mv -i'
alias cp='cp -i'
alias rm='rm -i'

Nota

Los ficheros se leen en orden alfabético, así que es buena idea hacer comenzar los nombres con números de igual longitud para la ordenación sea más evidente.

Si quisiéramos que los tres alias se definieran para todos los usuarios podríamos crear el fichero /etc/profile.d/bash_aliases.sh5

Hay una último aspecto interesante. En /etc/skell se almacena el esqueleto que se usa para crear los directorios personales de usuario. Cualquier fichero que se incluya aquí o cualquier modificación que se introduzca en los ficheros que ya existen, pasará a formar parte de los nuevos directorios personales que se creen.

2.4.3. Ejercicios sobre expansiones

  1. Crear el fichero vacio captura$1.jpg.

  2. Desde el directorio peronal y Utilizando expansiones, crear el siguiente árbol de directorios de la manera más corta posible:

    /tmp
      |
      +-- D1
      |    +-- D1a
      |    +-- D1b
      |    +-- D1c
      +-- D2
      |    +-- D21
      |    +-- D22
      |    +-- D23
      |    +-- D24
      |    +-- D25
      +-- DIR3
    
  3. Sin cambiar de directorio de trabajo, borrar los directorios D23 y D25 (hágalo del modo más corto posible).

  4. Mostrar por pantalla los directorios hijos de / que contengan la cadena «bin» en cualquier parte de su nombre.

  5. Mostrar los programas propios del administrador que contengan tres letras.

    Nota

    En los modernos sistemas Debian /sbin y /usr/sbin contienen lo mismo.

  6. Mostrar los programas propios del administrador que contengan al menos tres letras.

  7. Mostrar los programas propios del administrador que empiecen por «a» y acaben por cualquier vocal.

  8. Mostrar los programas propios del administrador que empiecen por vocal y acaben por vocal.

  9. Mostrar por pantalla todas las combinaciones con repetición que se pueden formar con dos vocales.

  10. Suponiendo que no se hayan creado usuarios con directorios personales en sitios extraños, ver los directorios personales de usuarios cuyo nombre empieza por «u».

  11. Comprobar cuántos dispositivos de almacenamiento (discos, memorias usb, …) hay en el sistema.

  12. Comprobar cuáles son las páginas de manual en español de la primera sección que empiezan por la letra «m».

  13. Lo mismo, pero en cualquier sección.

  14. Lo mismo, pero en cualquier sección y lengua.

  15. ¿Cuántos kernel de linux distintos hay instalados en el sistema?

    Nota

    Pruebe a buscarlos; no use herramientas como dpkg.

Notas al pie

1

En la consola interactiva puede escribirse la tabulación pulsado Ctrl+v y a continuación la propia tabulación.

2

Este comportamiento de no interpretar ante un patrón que no corresponde con ningún fichero puede modificarse mediate:

$ shopt -s nullglob

Hecho esto, un patrón que no tiene correspondencia se resolverá a la cadena nula:

$ echo Interpretación: /?
Interpretación: /?
$ shopt -s nullglob
$ echo Interpretación: /?
Interpretación:
3

Para que la nueva variable, se convierta en variable de ambiente es necesario exportarla.

4

Cuando un programa necesita hacer uso de un editor, está preparado para buscar entre las variables de ambiente el valor de EDITOR. Si existe, es este el valor que usa; si no es así, invoca un editor llamado sensible-editor, que es un programa que comprueba si está definida la variable SELECTED_EDITOR, cuyo valor es el editor preferido. Si lo está, ese es el editor que se lanza; si no, llama al programa selected-editor que permite elegir uno y define de forma persistente (en ~/.selected_editor) el valor de la variable. A partir de ese momento ese es el editor que se usará. El tercer mecanismo intuyo que jamás llega a operar.

5

/etc/profile.d/ esta organizado respecto a /etc/profile, del mismo que hemos nosotros aquí.