====== Uso del Shell Bash ====== El Shell es el programa que permite al usuario comunicarse con el //kernel// de Linux. Existen muchos shell, aunque el que se va a ver es el sell denominado "Bash", por ser uno de los más extendidos.\\ El shell Bash tiene una serie de opciones que definen su comportamiento. podemos ver estas opciones con el comando **set -o**. Para activar una opción hacemos **set -o [opción]**. Para desactivarla **set +o [opción]**.\\ Algunas de las opciones más interesantes son: * **allexport**: Exporta automáticamente toda variable creada o modificada en el proceso shell padre al proceso shell hijo, sin que sea necesario usar el [[linux:usobash#ambito_de_una_variable|comando export]]. Se puede activar con **set -a**. * **emacs**: Edición en línea de comandos estilo EMACS. * **vi**: Edición en línea de comandos estilo Vi. * **ignoreeof**: Especifica que se ignorará 10 veces el carácter EOF en la entrada. Idéntico a la [[linux:usobash#variables_de_entorno|variable de entorno]] IGNOREEOF=10. * **noclobber**: El shell no sobreescribe un archivo al realizar una [[linux:usobash#descriptores_de_archivos|redirección]] **>** a la salida (da un error). Para forzarlo hay que emplear la sintaxis **>|**. Puede activarse con **set -C**. * **noglob**: Desactiva la expansión de [[linux:usobash#caracteres_genericos|caracteres genéricos]] (no se permite su uso). Puede activarse con **set -f**. * **nounset**: Cuando se recurre a una [[linux:usobash#variables|variable]] inexistente, el shell da un error en vez de ignorarlo. Puede activarse con **set -u**. * **verbose**: Muestra las líneas de comandos a medida que se ejecutan. Útil para depurar. Puede activarse con **set -v**. * **xtrace**: A medida que se ejecutan los comandos, se muestra la expansión realizada de la variable de entprno PS4. Útil para depurar. Puede activarse con **set -x**. ===== Variables ===== Para definir una variable (no se especifica el tipo de cada variable), se utiliza la sintaxis [nombre_de_la_variable]=[valor], sin dejar ningún espacio. Ejemplos: var1=12 var2=palabra var3='dos palabras' var4=$'algunos car. especiales; $* ?{}()[]"\\&#' var5= Las variables se ponen por convención en minúscula, ya que se dejan las mayúsculas para las variables de entorno. Las variables están compuestas por letras, números y el carácter de barra baja. Sólo pueden empezar por una letra o barra baja. Se puede ver el valor de una variable con el comando **echo**. var1=12 echo La variable var1 es $var1 Para referirse a una variable se antepone '$' al nombre de la variable. Con el comando **set** podemos ver un listado de las variables en ese proceso (además de un montón más de cosas). Con el comando **unset** e indicando a continuación el nombre de la variable, eliminamos dicha variable. ==== Ámbito de una variable ==== Una variable sólo existe en el shell en el que se haya creado. Al salir de éste, las variables son automáticamente eliminadas.\\ Con el comando **bash** abrimos un shell que es un proceso hijo del shell en el que nos encontrábamos. De esta manera las variables son locales a cada shell. Para cerrar el "shell hijo" y volver al "shell padre", lo cerramos con **exit**.\\ Para que las variables del padre sean conocidas por el hijo, usamos el comando **export**: export x=3 bash echo $x 3 x=7 y=2 export y echo $y 2 exit echo $x 3 echo $y Con **export**, las variables creadas en el proceso padre pasan al hijo, pero nunca a la inversa. ===== Variables de entorno ===== Las variables de entorno se escriben por convención en mayúsculas. Estas variables son definidas al cargar la shell y afectan al comportamiento del mismo. Pueden verse todas (junto a muchas otras cosas) con el comando **set**. Puede verse su contenido con el comando **echo**. Algunas más importantes son: * **$BASH** Ruta al binario del Bash. * **$BASH_ENV** Apunta al archivo de arranque del Bash. Se lee al arrancar cada script. * **$EDITOR** Editor predeterminado (ruta absoluta). * **$HOME** Ruta completa del directorio personal del usuario conectado. * **$IGNOREEOF** Número de veces que ignorará el carácter EOF pasado mediante ctrl+d. * **$OLDPWD** Directorio donde se encontraba antes el usuario. Esta variable la usa el comando **cd -**. * **$PATH** Lista de directorios separados por **:**, con los ejecutables del sistema, en el orden en el que son buscados por el shell. PAra agregar un nuevo directorio: **PATH=$PATH:/[nuevo_directorio]** * **$PS1** Símbolo del sistema visto en la línea de comandos. Puede modificarse mediante diferentes modificadores: * \a Emite un //bip// al mostrar el símbolo del sistema. * \d Fecha. * \h Nombre de equipo. * \H Nombre de equipo y dominio. * \t Hora. * \u Nombre de usuario * \w ruta del directorio actual. * \W Nombre del directorio actual. * **$PS2** Símbolo del sistema secundario, que aparece cuando el shell espera el resto de la entrada de un comando. * **$PWD** Directorio donde se encuentra el usuario en ese momento. * **$TMOUT** Si es distinto de cero, indica el número de segundos en que desconecta el shell tras un periodo de inactividad. ===== Caracteres genéricos ===== En el bash, a la hora de especificar nombres de archivo, comandos, etc. es posible usar algunos caracteres denominados //genéricos//, para especificar cadenas de texto que desconocemos. * **Asterisco *** Sustituye a una cadena de caracteres alfanumérica de cualquier longitud, excepto al carácter **punto(.)**. Esto es por seguridad: no incluye a los archivos ocultos (empiezan todos con un punto). * **Interrogación ?** Funciona igual que el asterisco, con la salvedad de que se refiere a un único carácter. Podemos poner tantos **?** juntos como caracteres queramos especificar. * **Corchetes []** Entre los corchetes se especifica una lista de caracteres, de forma que la búsqueda se realiza para cada uno de ellos. Los caracteres van juntos. Es posible establecer varios caracteres de la tabla ASCII separados por un guión. Ejemplos: * ?[abc]*on Buscará nombres que empiecen por un carácter cualquiera, seguido de a, b, o c, seguido de una cadena de caracteres cualquiera terminada en ol. Ejemplo: raton, acabaron. * [a-zA-Z] Busca todas las palabras que sean letras bien mayúsculas, bien minúsculas. * Existen listas de caracteres predefinidas. Para especificarlas, dentro de los corchetes empiezan y terminan con dos puntos(:): * **[:alnum:]** Caracteres alfanuméricos. Equivale a [A-Za-z0-9], pero además incluye también a las letras del idioma configurado en el sistema (tildes, diéresis, etc.). * **[:alpha:]** Caracteres alfabéticos. Equivale a [A-Za-z]. * **[:digit:]** Caracteres numéricos. Equivale a [0-9]. * **[:graph:]** Caracteres imbrimibles (ASCII 33 a ASCII 126) excepto el espacio. * **[:print:]** Caracteres imbrimibles (ASCII 33 a ASCII 126) incluyendo el espacio. * **[:lower:]** Caracteres alfabéticos en minúscula. Equivale a [a-z]. * **[:upper:]** Caracteres alfabéticos en mayúscula. Equivale a [A-Z]. * **[:space:]** Equivale a cualquier espacio en blanco (espacio y tabulación). * **[:xdigit:]** Cifras hexadecimales. Equivale a [0-9A-Fa-f]. * **Llaves {}** Entre llaves, se especifican cadenas de caracteres separadas por comas, que serán buscadas. Todos estos caracteres genéricos pueden usarse en conjunto para realizar búsquedas más complejas. Por ejemplo: {*ro[sj]*,?a*} puede dar como resultado: banco, rosado o rojo. ==== Correspondencia extendida ==== Es posible indicar entre paréntesis y separados por **|**, diferentes patrones de búsqueda, de forma que se puede indicar con un carácter delante del paréntesis las condiciones de correspondencia que se deben cumplir: * **?(...|...|...)** Debe cumplirse una o ninguna correspondencia de los patrones indicados. * ***(...|...|...)** Debe cumplirse ninguna o varias correspondencia de los patrones indicados. * **+(...|...|...)** Debe cumplirse una o más correspondencias de los patrones indicados. * **@(...|...|...)** Debe cumplirse exactamente una o correspondencia de los patrones indicados. * **!(...|...|...)** No deben cumplirse ninguna correspondencia de los patrones indicados. Para usar esta característica, debe activarse la opción**extglob** des shell, con el comando **shopt**. ==== Caracteres de cita ==== Cuando queremos pasar caracteres especiales como caracteres normales, sin que el shell los interprete con su funcionalidad especial, usamos los caracteres de cita: * **apóstrofe '** Se ignoran todos los caracteres especiales incluidos entre apóstrofes. * **Comillas "** Se ignoran todos los caracteres especiales incluidos entre comillas, excepto dólar **$**, acento abierto **`** y barra invertida **\**. * **Barra invertida**: Ignora la función especial del carácter al que está unida. ===== Redirecciones ===== ==== Descriptores de archivos ==== Un descriptor de archivo es un puntero que apunta a un archivo.Cuando un programa lee o escribe en un archivo, utiliza un descriptor de archivo para para efectuar las operaciones.\\ Cualquier proceso en linux tiene tres descriptores de archivo, que se identifican con un número: * **Entrada (0)**: Por defecto la entrada estándar es el teclado. Para notificar el final de la entrada, en ocasiones es necesario enviar el carácter **EOF** con la combinación de teclas **ctrl + d**. * **Salida (1)**: Por defecto la salida estándar es el terminal. * **Error (2)**: Por defecto el descriptor de archivos por defecto es también el terminal. Si se desea enviar la entrada desde un archivo se utiliza el operador de redirección **<**. Por ejemplo: wc < /etc/passwd Para redireccionar la salida a un archivo, se utiliza el carácter **>**. Por ejemplo: echo > archivoTest Para redireccionar el error se utiliza **2>** para redirigir a un archivo los mensajes de error. Hay que tener en cuenta que cuando redirigimos las salidas a un archivo con los operadores de redirección, se sobreescribe el contenido. Para evitarlo simplemente se añade otro operador: **<<** o **>>**. También pueden combinarse todos los tipos de redirecciones de entrada, salida y error de forma simultánea, ejecutándolos siempre de izquierda a derecha. Ejemplo: comando < archivoEntrada > archivoSalida > archivoError Por último indicar que nunca se deben redirigir dos descriptores de archivo diferentes al mismo archivo, ya que esto provocaría resultados inesperados. La solución es usar la sintaxis [número descriptor]>&[número descriptor al que enviar los datos]. Ejemplo en el que no hay ningún archivo llamado "naranja": ls azul verde naranja rojo > archOut 2>&1 cat archOut ls: naranja No such file or directory azul rojo verde ==== Tuberías o "Pipes" ==== Ahora hemos visto como se podía enviar la salida de un proceso a un archivo. Las tuberías conectan procesos, de forma que la salida de un proceso va a la entrada de otro proceso. Las tuberías se indican con el carácter ** barra vertical |**. Ejemplo: ls | wc -l Puede usarse el comando **tee** como comando intermedio para consultar el resultado de un comando que a su vez será entrada de otro. Ejemplo: ls | tee /tmp/lista | wc -l ===== Generalidades sobre comandos ===== ==== Alias ==== Un alias reemplaza un comando, generalmente complejo, por un literal.\\ Pueden verse los alias existentes con el comando **alias** sin argumentos. Para definir un alias se usa la sintaxis **alias [nombreAlias]='[comando]'**. Para suprimir un alias se utiliza el comando **unalias [nombreAlias]**. Si un alias tiene un nombre igual al de un comando, siempre se ejecutará el alias, salvo que se especifique **\[nombreAlias]** o usar el comando **command**. Se puede suprimir todos los alias con el comando **unalias -a**. ==== Tipos de comandos ==== Existen dos tipos de comandos en Linux: * **Comandos Internos**: Comandos integrados en el shell. Puede verse un listado detallado de estos comandos en la página de manual del bash **man bash**. * **Comandos externos**: Son los archivos ejecutables presentes en el sistema de archivos, cuyas ubicaciones deben listarse en la variable de entorno $PATH. Si un comando externo tiene el mismo nombre que uno interno, se ejecutará el interno. Puede conocerse el tipo de comando con **type**. Para localizar la ubicación de un comando se usa **whereis**.