# 2.3.2.2 Exploración y manipulación de archivos

Con frecuencia es necesario el intercambio de datos y archivos entre el sistema operativo nativo (en este caso abordamos el caso de uso de Windows) y WSL. Los datos de muestra que se utilizan en el presente tutorial consisten en el resultado de búsqueda en "_Web of Science_" de artículos de investigación publicados desde el 2016 con los términos de búsqueda ("_epigenetics_" _AND_ "_nutrition_").

Los resultados de la búsqueda se encuentran en un archivo ._csv_, separado por comas, y pueden ser consultados en el siguiente [hipervínculo a google drive](https://drive.google.com/file/d/1mlSC6a31Ksi4j_gsWWKv5gMt5JVOH9k0/view?usp=drive_link). Deben ser descargados a la carpeta por defecto en Windows, y posteriormente se accederá a ella a través de la terminal de Linux.

Para copiar el archivo usaremos el comando `cp` que se revisó en la [unidad anterior](2.3.2.1-comandos-de-navegacion). En este caso, Windows en su versión 10 y 11, permite el acceso a los discos duros desde el directorio madre `/mnt/`, por lo que accedemos a la dirección de la carpeta de descargas empezando por este directorio. Posteriormente escribimos la dirección completa del archivo, seguido de un espacio y la carpeta de destino (/tmp/tutorial). El comando en su forma genérica se verá como la línea a continuación:

```
cp /mnt/c/Users/<Usuario>/Downloads/sample_data.csv /tmp/tutorial/
```

<figure><img src="https://4235622825-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyzFDWCsANohM6QBx4kmk%2Fuploads%2FspTid2ixw5Boc9tH6FtP%2Fimage.png?alt=media&#x26;token=fcce4423-bc16-4339-a52c-fc98487ea862" alt=""><figcaption></figcaption></figure>

Nos dirigiremos al directorio del archivo copiado para poder ejecutarlo desde la terminal, en el directorio de trabajo.

```
cd /tmp/tutorial
```

## <mark style="color:purple;">Visualizar datos con</mark> <mark style="color:purple;">`head`</mark> <mark style="color:purple;"></mark><mark style="color:purple;">y</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`tail`</mark>

Si bien podemos usar `cat` para visualizar este tipo de archivos, la longitud del texto hace difícil la visualización de su formato con esta función. Por esto resulta más práctico utilizar `head` y `tail`.  Con estas dos funciones se desplegará en la consola las primeras o últimas 10 líneas del archivo, respectivamente. Igualmente se puede especificar con la opción -n el número de líneas a imprimir.

```
tail -n 3 sample_data.csv
head -n 1 sample_data.csv
```

## _<mark style="color:purple;">Word count</mark>_ <mark style="color:purple;"></mark><mark style="color:purple;">(</mark><mark style="color:purple;">`wc`</mark><mark style="color:purple;">)</mark>

El comando `wc` realiza un recuento de los bites (`--bytes`, `-c`), caracteres (`-m`), palabras (`-w`) o líneas (`-l`) en un archivo, de acuerdo con la opción que se especifique al momento de invocarla. La sintaxis general, así como algunos ejemplos de código se muestran a continuación:

```
wc <opción> <archivo.extensión>
wc sample_data.csv # por defecto imprime el número de líneas, palabras y caracteres
wc -l sample_data.csv
wc -c sample_data.csv
```

Este comando también nos permite realizar un conteo de los archivos en un directorio.

```
ls | wc -l
```

## <mark style="color:purple;">Búsqueda de patrones con</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`grep`</mark>

El comando `grep` nos permite encontrar patrones de caracteres en un archivo. La ejecución del comando imprime todas las líneas que contengan el patrón consultado en la terminal.&#x20;

Algunas opciones útiles para aplicar la función `grep`, son:

* `-i` no distinguirá entre mayúsculas y minúsculas en el patrón a buscar.
* `-c` sólo mostrará el número de líneas coincidentes.
* `-r` realiza una búsqueda recursiva dentro del directorio de trabajo.
* `-n` busca las líneas coincidentes e imprime el número de la línea en el archivo además del contenido.
* `-v` imprime las líneas que no coinciden con el patrón de búsqueda.

La sintaxis general del comando así como algunos ejemplos se presentan a continuación:

```
grep <opción> <patrón> <archivo.extensión>
grep -c hypermethylation sample_data.csv
grep -n hypermethylation sample_data.csv
grep -v methylation sample_data.csv
```

## <mark style="color:purple;">Modificación de archivos con</mark> <mark style="color:purple;"></mark>_<mark style="color:purple;">translate</mark>_ <mark style="color:purple;"></mark><mark style="color:purple;">(</mark><mark style="color:purple;">`tr`</mark><mark style="color:purple;">)</mark>

El comando `tr` resulta muy versátil para la modificación de archivos, reemplazando caracteres o cadenas de caracteres, en patrones, o eliminándolos.&#x20;

Algunas opciones útiles para aplicar la función `tr`, son:

* `-c` todo carácter del archivo/línea que no coincida con el conjunto 1, se reemplaza por por el último carácter del conjunto 2.
* `-d` con esta opción se borran los caracteres del conjunto 1. No requiere especificar conjunto 2.
* `-s` sustituye las apariciones repetidas de un carácter en el conjunto 1 por una única aparición del mismo. No requiere especificar conjunto 2.
* `-t` trunca la longitud del primer conjunto de argumentos de acuerdo a la longitud que presenta el segundo. Si un elemento del conjunto 1 no tiene pareja en el conjunto 2, este es ignorado.

La sintaxis general del comando es:

```
tr <opción> <conjunto_caracteres_1> <conjunto_caracteres_2>
```

Donde los conjuntos de caracteres pueden consistir en:

* Listado de caracteres normales o de escape (\ n, \ t).
* Un rango de caracteres alfabéticos, por ejemplo todas las letras de la d a la f (d-f).
* Una repetición de caracteres exacta, por ejemplo tres veces repetida la letra a (a\*3).
* Una clase de caracteres por otra, por ejemplo \[:alnum:], \[:alpha:], \[:blank:], etc.

Algunos ejemplos de uso de la función `tr` se presentan a continuación:

```
echo "Esto es un ejemplo de uso de la función 'tr'" | tr 'E' 'e'

echo "Esto es un ejemplo de uso de la función 'tr'" | tr 'aeiou' 'AEIOU'
# esta última línea modifica todas las vocales minúsculas por mayúsculas

echo "Esto es un ejemplo de uso de la función 'tr'" | tr 'a-z' 'A-Z'
# esta línea modifica todas las letras sin acento de minúsculas a mayúsculas

echo "Esto es un ejemplo de uso de la función 'tr'" | tr '[:lower:]' '[:upper:]'
# de forma análoga, esta línea pasa las letras a mayúsculas, descritas como clase

echo "Esto es un ejemplo de uso de la función 'tr'" | tr '[:lower:]' '[:upper:]' > ejemplo_tr.txt
cat ejemplo_tr.txt
# esta línea pasa las letras del texto impreso a mayúsculas, y guarda el resultado en el archivo ejemplo_tr.txt

cat ejemplo_tr.txt | tr 'A-Z' 'a-z' >> ejemplo_tr.txt
cat ejemplo_tr.txt
# este conjunto de líneas modifica el archivo creado y añade el resultado al final del mismo
```

En el ejemplo a continuación se crea un archivo de valores separados por espacios "tab" (_tsv_) a partir del archivo sample\_data.csv, incluyendo únicamente aquellos artículos publicados en el año 2018, cuya información incluye la palabra "_metabolism_".

```
grep -i "metabolism" sample_data.csv | grep "2018" sample_data.csv | tr ',' '\t' > metabolism_2018.tsv
wc metabolism_2018.tsv
```

## <mark style="color:purple;">Ordenar las filas de un archivo con</mark> <mark style="color:purple;"></mark>_<mark style="color:purple;">sort</mark>_

El comando sort es útil para ordenar las filas en un archivo de datos. Este ordenamiento puede ser muy versátil a partir de las diferentes opciones que permiten especificarse. Su sintaxis general es:&#x20;

```
sort <opción> <archivo.extensión>
```

Algunas de las opciones que pueden especificarse son:

* `-b` para ignorar espacios en blanco.
* `-d` únicamente considera espacios en blanco y caracteres alfanuméricos, descarta caracteres especiales.
* `-f` se especifica para ignorar algún caso puntual.
* `-n` ordena los datos de acuerdo al número que precede a cada dato.
* `-c` cuenta la cantidad de datos ordenados y especifica aquellos que están por fuera de orden.
* `-u` elimina los duplicados en la salida ordenada.
* `-M` sirve para realizar un ordenamiento temporal para meses del año.
* `-k` sirve para especificar la columna sobre la que se quiere ejecutar el ordenamiento de los datos.
* `-t` especifica que el tipo de archivo a ordenar presenta un delimitador de campos. Por ejemplo para un archivo tipo _csv_ o _tsv_.
* `-r` indica que el ordenamiento de los datos se realizará de forma invertida.

En la siguiente línea de código se indica que se ordenen los datos del archivo sample\_data.csv, de acuerdo a los valores numéricos y de forma inversa, de la columna 7 (año de publicación).

```
sort -nr -t, -k7 sample_data.csv > sample_data_order.csv
```

## <mark style="color:purple;">Modificar archivos con el comando</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`sed`</mark> <mark style="color:purple;"></mark><mark style="color:purple;">(</mark>_<mark style="color:purple;">stream editor</mark>_<mark style="color:purple;">)</mark>

Con el fin de editar archivos de texto o de estructuras de datos es posible utilizar la terminal de Linux con el comando `sed` ("_stream editor_"). Este _programa_ es conocido como un editor de texto no interactivo, es decir que no se hace ediciones al archivo mismo que se invoca, sino que `sed` crea un espacio de memoria temporal o _buffer_, y es sobre éste último que actúa.&#x20;

El espacio de memoria temporal donde se crea el buffer es conocido como "_pattern space_", mientras que el espacio de memoria reservado para el archivo original es llamado "_hold space_".

Una de las funciones más relevantes de `sed` es la modificación -sustitución o eliminación- de cadenas de caracteres. La sintaxis general de esta instrucción es:

```
sed <opción(es)> 'orden(es)' <archivo(s)>
```

Las órdenes se pueden introducir directamente en la línea de código, o hacer que el programa las lea de un archivo de texto, en caso tal se indica la dirección. Las opciones son especialmente importantes al usar `sed`, puesto que al ser tan versátil, sólo a partir de esta especificación queda clara la orden que se da al programa.

### <mark style="color:purple;">Opciones del comando</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`sed`</mark>

Algunas opciones propias del programa `sed` son:

* `-e` hace que se implementen uno o múltiples comandos sed, que están explícitos en la línea ingresada. Consiste en la opción propia de la función por defecto, pero si se indica más de una orden en la misma línea de comando es mandatorio explicitar `-e`.
* `-f` indica que el comando se debe extraer a partir de un archivo adicional.
* `-n` indica que los resultados no se deben emitir en la consola. Cuando se indica `-n`, sólo las líneas del archivo que sufran modificaciones son impresas en consola, de lo contrario, todas las líneas van a mostrarse.
* `-i` crea un archivo temporal cuyas modificaciones pasarán a reemplazar al archivo original.
* `-u` no se utiliza un buffer de datos.
* `-s` indica que múltiples archivos se utilizan por separado en lugar de un único flujo de datos.
* `-r` hace que el comando acepte expresiones regulares ampliadas.

### <mark style="color:purple;">Órdenes del comando</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`sed`</mark>

La orden u órdenes, se especifican entre comillas simples, e indican la acción que debe llevar a cabo el programa sed. Algunas órdenes disponibles son:

* `a` (_append_): añade a las líneas seleccionadas una o más líneas nuevas.
* `c` (_change_): reemplaza las líneas indicadas por contenido nuevo.
* `d` (_delete_): elimina las líneas seleccionadas.
* `g` (_get_): copia el contenido del espacio temporal (_pattern space_) al archivo final (_hold space_) de forma permanente.
* `G` (_get new line_): añade el contenido del espacio temporal (_pattern space_) al archivo final (_hold space_) de forma permanente.
* `h` (_hold_): copia el contenido de la memoria temporal (_pattern space_) al archivo final (_hold space_) de forma permanente.
* `H` (_hold new line_): añade el contenido de la memoria temporal (_pattern space_) al archivo final (_hold space_) de forma permanente.
* `i` (_insert_): inserta una o más líneas antes de las líneas indicadas.
* `l` (_listing_): muestra todos los caracteres que no son imprimibles.
* `n` (_next_): cambia hacia la siguiente orden de la línea siguiente del comando.
* `p` (_print_): imprime, muestra en la consola las líneas seleccionadas.
* `q` (_quit_): finaliza el comando sed de Linux.
* `r` (_read_): lee las líneas indicadas a partir de un archivo.
* `s` (_substitute_): reemplaza una determinada cadena de caracteres por otra.
* `x` (_xchange_): intercambia la memoria temporal (_pattern space_) por la memoria final (_hold space_) del archivo de trabajo.
* `y` (_yank_): sustituye un carácter determinado por otro.
* `w` (_write_): escribe líneas en el archivo de texto.
* `!` (negación): aplica el comando especificado a las líneas que no coincidan con la condición dispuesta en la opción indicada.

Finalmente, las órdenes se pueden complementar con alguna de las siguientes opciones:

* `=` indica el número de línea de las líneas seleccionadas.
* `p` muestra las líneas modificadas.
* `q` aplica la orden a todo el archivo.

### <mark style="color:purple;">Expresiones regulares</mark>

Algunos signos de puntuación son utilizados en la sintaxis del comando sed para garantizar el ahorro de escritura en la línea de comandos y complejizar el tipo de tareas que este puede realizar.

* \[ABC]: en este caso usamos **corchetes** para indicar que alguno de los objetos dentro de ellos debe coincidir con la búsqueda en cuestión. Sea A, B o C.
* (ABC): los **paréntesis** indican que se busca el objeto específico compuesto de los caracteres ABC en este orden específico.
* .    ->    el **punto** actúa como un comodín que indica que un carácter puede aparecer en su lugar.
* \*   ->    el **asterisco** indica que cualquier número de caracteres puede aparecer en su lugar.
* ?    ->    el signo de interrogación indica que un término puede aparecer una o ninguna vez.
* \+    ->    el signo de adición indica que el carácter en cuestión aparece varias veces, como mínimo una.
* {0,n}    ->    un número entre llaves, indica la frecuencia exacta de  aparición de un carácter o cadena de caracteres. Dos números a modo de pareja ordenada, separados con una coma, indican el número mínimo y máximo como un intervalo de repeticiones permitidas.
* \|    ->    la barra vertical o pleca indica disyunción entre dos opciones a indicar.
* ^    ->    el acento circunflejo indica negación. Es decir que el patrón indicado a continuación se encuentra negado, no debe aparecer.

### <mark style="color:purple;">Ejemplos de uso del comando</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`sed`</mark>

Por medio del siguiente comando se indica la impresión en consola de las líneas 10 a 50 del archivo de muestra "sample\_data.csv".

```
sed -n '10,50p' sample_data.csv
```

Por medio del siguiente comando se realiza una búsqueda de términos concretos en un documento. Esto es útil para bases de datos extensas o códigos fuente. Específicamente se indica que se imprima la primera línea del documento, y posteriormente todas las líneas que contengan el término "_metabolic_". Es decir, se introducen dos comandos seguidos, denotados por la opción `-e`.

```
sed -n -e '1p' -e '/metabolic/p' sample_data.csv
```

## <mark style="color:purple;">Extraer información con el comando</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`cut`</mark>

&#x20;La principal función del comando `cut` es extraer información de un archivo de texto, sea indicando por número de caracteres o separadores de columnas. La forma en que se extraen los datos se indica con las opciones de la función. La sintaxis general del comando es:

```
cut <opción> <patrón> <archivo.extensión>
```

Algunas opciones disponibles para invocar el comando `cut` se presentan a continuación:

* -c indica que la dirección para extraer información se está dando en posición de caracteres.
* -d indica que la dirección para extraer información se está dando en columnas con un delimitador en particular.
* -z indica que el archivo de texto se considera como una única línea, y la dirección se entrega como posición de los caracteres.
* -s indica que las líneas que no contengan el delimitador especificado deben ser ignoradas.
* -b indica que la dirección para extraer la información se dará en forma de bytes.

### <mark style="color:purple;">Ejemplos de uso del comando</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`cut`</mark>

A continuación se presentan algunos ejemplos de uso del comando `cut` con una línea de texto. En un archivo de múltiples líneas cada comando se ejecutaría en todas las líneas a la vez, a excepción del uso de la opción `-z`, que trata todas las líneas como una única línea.

```
echo 'este es un ejemplo de uso del comando cut' | cut -c 2
# esta línea imprime el carácter de la posición 2 de la frase impresa

echo 'este es un ejemplo de uso del comando cut' | cut -c 2-8
# esta línea imprime los caracteres 2 a 8

echo 'este es un ejemplo de uso del comando cut' | cut -c 6,18
# esta línea imprime los caracteres 6 y 18

echo 'este es un ejemplo de uso del comando cut' | rev | cut -c 1,2 | rev
# esta línea invierte la frase escrita, extrae los caracteres 1 y 2, e invierte su orden

echo 'este es un ejemplo de uso del comando cut' | cut -c 5-
# esta línea imprime los caracteres a partir de la posición 5

echo 'este es un ejemplo de uso del comando cut' | cut -c -7
# esta línea imprime los caracteres hasta la posición 7
```

En el siguiente ejemplo utilizamos el comando `cut` para visualizar la columna de los códigos _DOI_ de los artículos de la base de datos que construimos anteriormente.

```
cut -d ',' -f12 sample_data.csv
```

En el comando anterior, la opción `-d` indica que se especifica un delimitador, y se especifica por una coma. `-f12` indica que la fracción delimitada está entre los delimitadores 11 y 12, y finalmente se entrega el nombre del archivo.&#x20;

Con el siguiente comando se extrae la columna de '_Source Title_' y se almacena en el archivo 'journal.txt'.

```
cut -d ',' -f1 sample_data.csv > journal.txt
```

## <mark style="color:purple;">Extraer líneas únicas con el comando</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`uniq`</mark>

El comando `uniq` elimina las líneas repetidas que se encuentran **adyacentes** unas a otras en un archivo. La condición de adyacencia hace que sea necesario ordenar previamente los datos con el comando `sort`. En el caso de que la estructura de los datos contenga diferentes columnas, la comparación de las líneas se puede hacer de acuerdo a líneas completas o una columna en particular, especificando el tipo de separación de los campos (por ejemplo comas, espacios o tabulaciones).&#x20;

Algunas opciones propias de la función `uniq` son:

* `-c` indica que frente a cada línea única se imprima el número de apariciones.
* `-d` se imprimen únicamente las líneas repetidas.
* `-f` indica que se debe ignorar el número de campos (columnas) especificados por la variable _F_.
* -u se imprimen únicamente las líneas que no se repiten.
* `-s` indica que se debe ignorar un número de caracteres (bytes) especificados por la variable _S_. Si se especifican ambas opciones, `-f` y `-s`, primero se ubica la función sobre el campo indicado y después sobre el carácter indicado.

```
sort journal.txt | uniq -c > journal_sorted.txt
```

Con la anterior línea de comando ordenamos en forma alfabética los títulos de las revistas de nuestro archivo 'journal.txt', seguido de eliminar duplicados e indicar el número de apariciones de cada nombre. Finalmente se guarda el resultado en un nuevo archivo de nombre 'journal\_sorted.txt'.
