Ocultando archivos en GNU/Linux
Una de las facilidades que nos ofrece lo sistemas basado en Unix es su facilidad para configurarlo sin tener que tocar un gran y sobrecargado registro (haciendo referencia a Microsoft Windows) sino que modificando simple archivos de texto podemos ajustar las preferencias de nuestros programas o de nuestro sistema, un ejemplo de esto es la forma como se oculta un archivo y/o carpeta en los sistemas basado en Unix porque simplemente anteponiendoles un punto al nombre del archivo este se vuelve un archivo oculto para el sistema. Viendo esta facilidad para ocultar un archivo en nuestra distribución Linux, practiquemos un poco con Python creando un pequeño pero funcional script que oculte un archivo.
Comencemos planteando como llevar nuestra necesidad de ocultar un archivo en GNU/Linux con Python, por ahora tenemos dos cosas como para comenzar una es que nuestra función tiene que tomar un archivo como parámetro para funcionar y la otra es como se oculta un archivo, llevándolo al papel nos quedaría algo así como para orientarnos en la construcción de la función:
- Entra como parámetro un archivo
- Si ya esta oculto no se realizaría ninguna acción
- Si no esta oculto colocamos como primer carácter en el nombre un punto
Habiéndolo planteado empecemos por el punto numero 1, nuestro Linux no discrimina si se trata de un archivo o de una directorio utiliza el mismo método para ocultarlos así que comprobar con que estamos trabajando podemos dejarlo de lado por un momento, algo que si es importante es que obviamente el archivo debe existir. Para comprobar la existencia del archivo podemos tomar como referencia lo visto en “Tres formas de comprobar la existencia de un archivo” utilizando la primer forma, ya que como mencione no estamos discriminando si se trata de un archivo o una carpeta y no tendría ningún sentido utilizar la segunda forma. La primer forma para comprobar la existencia de un archivo que vimos fue esta:
archivo = "/usr/bin/firefox"
def checkfile(archivo):
import os.path
if os.path.exists(archivo):
print "El fichero existe"
else:
print "El fichero no existe"
Como podrán ver cumple con su objetivo y nos va a servir para mas adelante, por ahora dejemoslo y sigamos con la segunda parte de nuestro ocultador de archivos para sistemas tipo Unix. Lo segundo en nuestra lista es “Si ya esta oculto no se realizaría ninguna acción” pero para esto tenemos que tener en cuenta dos factores importantes uno es con que archivo o carpeta estamos trabajando realmente y lo segundo es como saber si el primer carácter es un punto y en consecuencia de que se trate de un archivo ya oculto, paso a explicar lo primero que mencione sobre como saber con que estamos trabajando realmente, supongamos que el usuario pasa como parámetro la siguiente ruta a un archivo “/usr/bin/firefox” uno fácilmente puede deducir que se puede tratar de un archivo o una carpeta que se llama “firefox” y de que “/usr/bin/” es la ruta al mismo y que es con lo que debemos trabajar, pero como hacemos para que Python discrimine esto y sin intervención nuestra para superar este inconveniente. Para lograr esto tenemos dos formas una con ‘os.path.split’ y la otra con ‘os.path.basename’, paso a explicar las diferencias de cada uno así como sus ventajas y sus desventajas:
* ‘os.path.split’:
Su espacio en la documentación de Python:
http://docs.python.org/library/os.path.html#os.path.split
Información extraída de The Python Standard Library:
Split the pathname path into a pair, (head, tail) where tail is the last pathname component and head is everything leading up to that. The tail part will never contain a slash; if path ends in a slash, tail will be empty. If there is no slash in path, head will be empty. If path is empty, both head and tail are empty. Trailing slashes are stripped from head unless it is the root (one or more slashes only). In all cases, join(head, tail) returns a path to the same location as path (but the strings may differ).
Paso a explicar que es lo que hace esta función, la función toma una ruta como argumento y devuelve una tupla con dos valores uno de ellos es el directorio donde se encuentra el archivo con el que estamos trabajando y por otro lado devuelve también el nombre de archivo o carpeta, así que nos devuelve dos valores uno es el directorio del archivo y el otro es el archivo. Pongamoslo en un ejemplo para darnos cuenta de lo que hablamos:
>>> import os.path # Obviamente deberemos importar el modulo para poder utilizarlo
>>> file = "/usr/bin/firefox" # El archivo a analizar
>>> os.path.split(file) # La función que hará todo el trabajo con la ruta como argumento
('/usr/bin', 'firefox') # Acá podemos ver la salida de la función
>>>
Como observaran el primer valor es el directorio y el segundo es el archivo, así que podemos asignar esta tupla en dos variables con los valores en cuestión quedándonos algo parecido a esto:
>>> import os.path >>> file = "/usr/bin/firefox" >>> split = os.path.split(file) # Esta ves asignamos salida de la función a una variable >>> ruta = split[0] # En estas dos lineas asignamos las variables que les mencionaba >>> archivo = split[1] >>> print "La ruta es %s y el archivo %s" % (ruta, archivo) La ruta es /usr/bin y el archivo firefox >>>
* ‘os.path.basename’:
Su espacio en la documentación de Python:
http://docs.python.org/library/os.path.html#os.path.basename
Información extraída de The Python Standard Library:
Return the base name of pathname path. This is the second half of the pair returned by split(path). Note that the result of this function is different from the Unix basename program; where basename for ‘/foo/bar/’ returns ‘bar’, the basename() function returns an empty string (”).
Esta función también toma como argumento la ruta con la que deseamos trabajar y nos devuelve el archivo o carpeta a donde apunta la ruta que pasemos como parámetro, veámoslo en acción:
>>> import os.path # Obviamente deberemos importar el modulo para poder utilizarlo >>> file = "/usr/bin/firefox" # La ruta que les mencionaba >>> os.path.basename(file) # La función que hará todo el trabajo con la ruta como argumento 'firefox' # Acá podemos ver la salida de la función >>>
Esta función a diferencia de ‘split’ solo devuelve la base de la ruta que pasemos como parámetro, excluyendo el directorio donde se encuentra siendo un resultado mas conciso.
Quizás no haya explicado en profundidad estas dos funciones, pero con lo que sabemos hasta ahora tenemos como para continuar con nuestra miniaplicacion, porque si volvemos para atrás vamos a recordar que toda esta explicación era para responder una de las preguntas que plantee ¿Como saber con que archivo/carpeta debemos trabajar? ahora ya podemos conseguir esto sin nuestra intervención, pero todavía nos falta una parte ¿Como saber si el primer carácter es un punto?, pero antes de seguir quizás algunos de ustedes se pregunten para que plantearnos esto, pues la respuesta es muy simple porque tenemos que pensar que sentido tiene ocultar un archivo oculto agregando mas de un punto al inicio de su nombre, así que ahora que ya entendimos el porque volvamos con lo que estábamos.
Para detectar si el primer carácter es un punto simplemente aplicando (lo que ya deberían de conocer sino es así a volver a estudiar
) las operaciones básicas sobre cadenas vamos a ver que esto es extremadamente simple, lo que deseamos hacer es ver si el archivo con el que estamos trabajando esta ya oculto para esto como mencione anteriormente debemos ver si el primer carácter es un punto, para esto debemos recordar las operaciones sobre cadenas y que para ver un carácter especifico de una cadenas la operación es la misma que para ver un valor de una tupla o una lista, veámoslo con ejemplos:
La palabra que analizaremos sera “GNU/Linux” que la asignaremos a la variable “palabra”
>>> palabra = "GNU/Linux"
Supongamos que queremos ver el primer carácter de nuestra cadenas, para esto debemos recordar que el índice comienza con 0 y no con 1
>>> palabra[0] 'G' >>>
Como vemos ya estamos listos para seguir con nuestro objetivo principal, pero antes con todo lo que ya vimos podemos empezar a construir nuestra miniaplicacion pero recordemos los tres argumentos principales de nuestro script planteados al inicio del tutorial:
1 – Entra como parámetro un archivo
2 – Si ya esta oculto no se realizaría ninguna acción
3 – Si no esta oculto colocamos como primer carácter en el nombre un punto
Con lo visto ya podemos armar los dos primeros, primero armemos la primer parte en donde habíamos visto esto:
archivo = "/usr/bin/firefox"
def checkfile(archivo):
import os.path
if os.path.exists(archivo):
print "El fichero existe"
else:
print "El fichero no existe"
Para esto debemos eliminar el código que no nos sirve como las sentencias ‘print’ y el ‘else’ del condicional pero vamos de a poco, primero saquemoslo de la función para poder incluirlo en nuestra futura aplicación
import os.path
if os.path.exists(archivo):
print "El fichero existe"
else:
print "El fichero no existe"
Si nos ponemos a pensar (se que es difícil pero hay que intentarlo) solo con el ‘if’ podemos satisfacer nuestras necesidades porque nosotros solo necesitamos que la función se detenga si no se encuentra el archivo, por esto mismo si utilizamos ‘not’ un operador lógico que niega lo que le pongamos después de el estamos cumpliendo con todo lo que necesitamos, volvamos con los ejemplos:
if not os.path.exists(archivo):
return
Vamos a traducir esto, el ‘if’ se traduce como ‘si’ y el ‘not’ como ‘no’, con un ingles básico es fácil traducirlo, una traducción seria si no existe el archivo terminar la ejecución de nuestra aplicación, como vimos esta forma es mucho mas sencilla y es la que vamos a utilizar.
Habiendo pulido la primera parte vamos con la segunda, para mostrarles como era que íbamos a comprobar si el archivo ya se encontraba oculto les puse un ejemplo pero ahora es hora de plantearlo para nuestra necesidad, lo tenemos que hacer es ver si el primer carácter de nuestro archivo es un punto y por supuesto como obtener el nombre de nuestro archivo y enviarlo a una variable:
if archivo[0] == '.':
return
La sentencia ‘return’ esta porque no necesitamos realizar ninguna acción si el archivo ya esta oculto, pero acá nos esta faltando algo, como obtener el nombre del archivo que nosotros acabamos de analizar. Si volvemos para atrás vamos a recordar que les mostré dos funciones incluidas en el modulo ‘os’, una era ‘split’ y la otra ‘basename’ la que pienso utilizar es la ultima mencionada de las dos, para usarla es tan simple como crear una variable a la que le asignamos la salida de la funcion ‘basename’ quedando así:
archivo = os.path.basename(file)
Habiendo terminado esto podríamos crear una función llamada ‘hide’ que tome como argumento un archivo y en ella agregaremos lo que tenemos hasta ahora:
def hide(file):
import os
if not os.path.exists(file):
return
archivo = os.path.basename(file)
if archivo[0] == '.':
return
Hasta ahora solo podemos analizar si el archivo esta oculto o no, pero nos falta darle la facultad a esta función de poder ocultar archivos de ser necesario, con esto anuncio que estamos listos para pasar al tercer y ultimo punto del día de hoy:
3 – Si no esta oculto colocamos como primer carácter en el nombre un punto
Antes de comenzar dejenme recordarles algo muy básico pero a su ves muy importante en este caso sobre como vamos a tratar a la cadena que contendrá el nombre del archivo, las cadenas a diferencias de por ejemplo las listas son inmutables, con esto dejamos en claro que no vamos a poder cambiar la cadena existente, nuestra solución a esto es crear una nueva cadena en la cual pongamos como primer carácter un punto. Para conseguir que la nueva cadena tenga ese tan preciado punto debemos remontarnos a algo muy básico en las operaciones sobre cadenas y es la concatenación, como lo veremos a continuación conseguir esa nueva cadena es muy simple:
nuevoarchivo = '.' + archivo
Veámoslo en acción:
>>> nuevoarchivo = '.' + archivo # Como verán aquí estamos uniendo el punto con el nombre del archivo >>> nuevoarchivo # Llamamos a nuestra nueva cadena '.firefox' # y vemos como logramos colocar ese punto delante del nombre >>>
Como vemos funciona y estamos listos para ocultar nuestros archivos con Python, este maravilloso lenguaje nos trae dentro del modulo ‘os’ una función llamada ‘rename’ que hará el proceso de renombrar el archivo que deseamos. La función ‘rename’ esta disponible tanto para sistemas Windows como para sistemas Unix lo que lo vuelve multiplataforma y nos asegura que no vamos a tener inconvenientes en usarlo en nuestra aplicación, volviendo a su aplicación esta función toma dos argumentos para su funcionamiento, que como se imaginaran uno es el archivo de origen y el otro es el de destino, esto quiere decir que por un lado le indicamos el archivo que deseamos renombrar y por el otro el nuevo archivo que deseamos crear, en nuestro caso queremos pasar del archivo ‘firefox’ al archivo ‘.firefox’. Viendo esto en lo llevamos en nuestra aplicación sabemos que el archivo de origen es el que asignamos a la variable ‘file’; una aclaración que debo hacer con respecto de ‘rename’ es que debemos usar no el nombre del archivo sino que el archivo junto con la ruta del mismo es por esto que debemos usar la variable ‘file’ que tiene la ruta completa del archivo, una solución a esto es cambiar la carpeta con la que trabaja nuestro interprete de Python, para que quede un poco mas claro esto voy dejar de lado nuestro script para dejar un poco mas en claro lo que les acabo de mencionar.
La función ‘rename’ como les mencionaba le debemos indicar la ruta completa del archivo tanto para la entrada como para la salida, en caso de que no le demos la ruta completa en la salida de ‘rename’ moverá nuestro archivo a la carpeta donde este trabajando nuestro interprete, para averiguar cual es la carpeta con la que estamos trabajando debemos en nuestro interprete de Python escribir esto:
import os # Deberemos importar el modulo 'os' para que funcione os.getcwd() # Esta es la función que nos entregara la carpeta que estamos buscando
En mi caso la salida es esta:
>>> import os >>> os.getcwd() '/home/alejandro' >>>
Como se imaginaran en caso de no dar la ruta completa en la salida de la función ‘rename’ me movería el archivo a esa carpeta, viendo este inconveniente como un imprevisto de los cuales hay muchísimos a la hora de trabajar debemos analizar cuales son las posibles soluciones a esto, como ya voy extendiéndome demasiado con un script tan simple y los veo impacientes de tanto leer les voy a mostrar tres formas de darle una solución a esto.
La primera que se nos puede ocurrir es reveer lo que hicimos hasta ahora y volver a la parte cuando les mencione la función ‘split’ la cual nos dividía la ruta que le dábamos en dos partes una con la carpeta que contenía al archivo y el nombre del archivo, si optamos por esto deberíamos descartar el uso de ‘basename’ para obtener el nombre del archivo cosa que en nuestro caso seria simplemente modificar unas lineas porque tenemos la suerte de estar trabajando con un script de muy pocas lineas y que no es muy complejo así que no deberíamos tener inconvenientes en usar ‘split’ en lugar de ‘basename’. Pero antes de ponernos a modificar todo lo que ya hicimos y que hasta ahora funciona, veamos que otras soluciones tenemos disponibles. Otra solución es cambiar la carpeta donde esta trabajando nuestro interprete por la ruta del archivo que deseamos cambiar el nombre, en este punto nos surge un inconveniente el cual es que no tenemos la carpeta que contiene al archivo así que debemos plantearnos una forma de obtener esa carpeta y asignarla a una variable para su posterior uso en nuestro script, tenemos como mencionaba antes el uso de ‘split’ para conseguir esto pero si revisamos bien en la documentación de Python nos vamos a encontrar con ‘dirname’ que hace casi lo mismo que ‘split’, lo que hace ‘dirname’ es entregarnos lo mismo que nos da el primer valor de la tupla de ‘split’, asi que hasta ahora tenemos dos formas una es usar desde un inicio ‘split’ y la otra es utilizar ‘dirname’ junto con ‘basename’ y tendríamos los mismos resultados.
Como la desicion este tutorial no es democrática voy a optar por usar ‘dirname’, pero antes veamos esto acción para ver si realmente funciona:
>>> import os # Importamos el modulo 'os' >>> file = "/usr/bin/firefox" # Esta va a ser la ruta a analizar >>> os.path.dirname(file) # Usamos la función '/usr/bin' # y vemos que funciona de maravilla >>>
Ahora si podemos reclinar nuestra silla como señal de satisfacción por haber solucionado nuestro problema mas “complejo” a lo largo del tutorial, pero tampoco hay que festejar antes de terminar lo que empezamos así que no sean perezosos y continuemos, si mal no recuerdo nunca habíamos tenido el placer de ver en acción a la función ‘rename’ la había mencionada pero nunca la testeamos. Para probar esta función cree un archivo llamado ‘Codigo-Python’ el cual esta ubicado en la carpeta donde trabaja mi interprete, vayamos a teclear un poco:
>>> import os # Como de costumbre importamos el modulo 'os'
>>> os.rename('Codigo-Python', '.Codigo-Python') # Como verán esta el archivo de origen y el de destino
Si volvemos a ver en esa carpeta no debería ser visible nuestro archivo, salvo que por ejemplo si estamos usando ‘Nautilus’ presionemos CTRL + H deberían de aparecer los archivos ocultos entre los cuales debería estar el nuestro y así corroborar que esta función cumple con nuestra necesidad, ahora si juntemos lo que vimos:
directorio = os.path.dirname(file) # Creamos una variable con la ruta nuevoarchivo = directorio + '/''.' + archivo # Ya explico el porque de la contecatenacion aplicada os.rename(file, nuevoarchivo) # y por ultimo llamamos a la función 'rename'
La primer linea así como la tercera no es necesaria explicarla pero en la segunda nos encontramos con un cambio con respecto a lo que ya les había mostrado, porque volviendo para atrás yo les había mostrado lo siguiente:
nuevoarchivo = '.' + archivo
Si lo comparamos obviamente vemos la inclusión de la variable ‘directorio’ que contiene la ruta hacia el archivo a renombrar, pero aparece esta variable concatenada con el siguiente carácter ‘/’ esto se debe a que como ya habíamos como funcionaba la función ‘dirname’ y si lo observan bien no coloca la barra al final de la dirección la cual es necesaria para poder utilizarla en nuestro script, al realizar estas dos concatenaciones estas teniendo por un lado la ruta con la barra diagonal al final ‘/usr/bin/’ y por otro lado el nombre con un punto adelante ‘.firefox’ y con esto tendremos listo nuestro script solo es cuestion de armar lo que ya hicimos quedando algo así:
def hide(file):
import os
if not os.path.exists(file):
return
archive = os.path.basename(file)
if archive[0] == '.':
return
else:
directorio = os.path.dirname(file)
newfile = directorio+'/''.'+archive
os.rename(file, newfile)
Como finalización de esta primera parte espero haber planteado la base de como encarar (de una forma un tanto desprolija lo admito) el inicio de un proyecto personal con Python y empezar a desarrollar nuestras primeras aplicaciones con este lenguaje, seguramente habré repetido algunos procedimientos o explicaciones pero la razón de esto es poder ofrecer una guía paso a paso apta para los que recién comienzan con la programación (me incluyo en esto ultimo). Sin mas que decir por el día de hoy me despido y nos veremos en la segunda parte de este tutorial en donde a diferencia de esta primera parte donde nos concentramos por ocultar los archivos, ampliaremos su capacidad dándole la posibilidad de mostrar archivos ocultos, pero eso lo veremos en la segunda parte.
Unos links que les pueden ser útiles
Sobre ‘rename’:
http://docs.python.org/library/os.html#os.rename
Sobre ‘split’, ‘basename’ y ‘dirname’
http://docs.python.org/library/os.path.html#os.path.split
http://docs.python.org/library/os.path.html#os.path.basename
http://docs.python.org/library/os.path.html#os.path.dirname
Un articulo sobre Linux y los archivos ocultos:
http://huevas.wordpress.com/2007/08/19/archivos-ocultos-en-linux/
Seguí este post también en:
http://snipplr.com/view/50039/hiding-files-in-gnulinux/
Si ves que este post merece alguna modificación sentite libre de hacerlo a través de nuestra Wiki siguiendo el siguiente enlace:
http://wiki.codigopython.com.ar/pyhide:ocultando-archivos-en-gnu-linux
Pingback: Mostrando archivos ocultos en GNU/Linux
Pingback: Bitacoras.com