Shell script emulando una papelera

16 envíos / 0 nuevos
Último envío
#1 Jue, 26/05/2016 - 10:50
mcgregor
Imagen de mcgregor
Desconectado/a
se unió: 26/05/16

Shell script emulando una papelera

Estado: 
[ACTIVO]

Se nota que el foro esta recien creado, bueno voy a estrenar la seccion. laugh

 

Vereis, estoy haciendo un script emulando una papelera de reciclaje, es un trabajo para el instituto.

El tema es que la opcion de borrar archivos me funciona bien, incluyendo los comodines "*" y "?", pero cuando le pongo un rango me falla.

Me explico, si le digo que me borre esto (suponemos que existen los archivos "archivo1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13"):

/home/alumno/archivo[1-12]

Solo me mueve a la papelera los arhivos 1 y 2 (archivo1, archivo2) y no se por que.

Este es el codigo (con ver la opcion a) del CASE sobra): (parece largo, pero es muy sencillo)

clear

if [ ! -d $HOME/papelera ]
then
	mkdir $HOME/papelera
fi

papelera="$HOME/papelera/"
op=a
archivos=0
carpetas=0

until [ $op = x ]
do
	echo
	echo ----------------------------------------
	echo a - Borrar archivo
	echo b - Muestra el contenido de la papelera
	echo c - Recupera un archivo
	echo d - Vacia la papelera
	echo x - Salir
	echo ----------------------------------------
	read op

	case $op in
	a)
		contenido=`ls "$papelera" | wc -l`

		if [ $contenido -lt 10 ]
		then
			echo Introduzca el nombre del archivo a borrar, incluida la ruta
			read archivo

			if [ -f "$archivo" ]
			then
				mv $archivo $papelera
				contenido=`ls "$papelera" | wc -l`

				if [ $contenido -ge 10 ]
				then
					clear
					echo
					echo --------------
					echo PAPELERA LLENA
					echo --------------
					echo
				fi
			else
				for file in $archivo
				do
					mv "$file" $papelera
					contenido=`ls "$papelera" | wc -l`

					if [ $contenido -ge 10 ]
					then
						clear
						echo
						echo --------------
						echo PAPELERA LLENA
						echo --------------
						echo
						break
					fi
				done
			fi
		else
			clear
			echo
			echo --------------
			echo PAPELERA LLENA
			echo --------------
			echo
		fi
		;;
	b)
		contenido=`ls "$papelera" | wc -l`

		if [ $contenido -eq 0 ]
		then
			clear
			echo
			echo ---------------
			echo PAPELERA VACIA
			echo ---------------
			echo
		else
			clear
			echo Contenido de la papelera
			echo -------------------------------------------
			ls -lA $papelera
			echo -------------------------------------------
			echo Resumen:

			for fich in $papelera/*
			do
				if [ -f "$fich"  ]
				then
					archivos=`expr $archivos + 1`
				elif [ -d "$fich" ]
				then
					carpetas=`expr $carpetas + 1`
				fi
			done

			echo Carpetas:$carpetas -  Archivos:$archivos
			echo -------------------------------------------
			echo -------------------------------------------
			echo
			carpetas=0
			archivos=0
		fi
		;;
	c)
		echo Introduce el nombre del archivo a recuperar
		read archivo

		if [ -f "$papelera/$archivo" -o -d "$papelera/$archivo"  ]
		then
			archivo="$papelera/$archivo"
			echo Directorio de recuperacion:
			read dirRecu

			if [ -d "$dirRecu" ]
			then
				mv "$archivo" "$dirRecu"
				clear
				echo
				echo ------------------
				echo Archivo recuperado
				echo ------------------
				echo
			fi
		else
			clear
			echo
            echo --------------------
            echo El archivo no existe
            echo --------------------
            echo
		fi
		;;
	d)
		echo Desea vaciar la papelera? \(s/n\)
		read vaciar

		if [ $vaciar = s ]
		then
			rm -r $papelera/*
			clear
			echo
			echo ----------------
			echo Papelera vaciada
			echo ----------------
			echo
		fi
		;;
	x)
		echo Saliendo
		break
		;;
	esac
done

Existe un límite de archivos en la papelera de 10, pero eso no afecta.

Bien, ¿por que no me coje bien el rango?

Muchas gracias de antemano y espero que este foro llegue a tener tanta informacion como tuvo en su día esDebian (una pena lo de su cierre)

 

P.D. Podeis coger el código y hacer lo que querais con el, jejejejeje, os agradeceria si me dijieseis alguna mejora. Gracias. wink

Jue, 26/05/2016 - 12:27
caliban
Imagen de caliban
Desconectado/a
moderador
se unió: 14/01/16

Si queres suministrar un rango , y por ejemplo tenes ( si te he entendido bien ) 

archivo1,archivo2,archivo3,archivoN

Y queres indicar el rango 

mv archivo{1..N} # donde N=numero final del rango  

en tu caso  archivo{1..12}

Jue, 26/05/2016 - 13:04 (Responder a #2)
mcgregor
Imagen de mcgregor
Desconectado/a
se unió: 26/05/16

caliban wrote:

Si queres suministrar un rango , y por ejemplo tenes ( si te he entendido bien ) 

archivo1,archivo2,archivo3,archivoN

Y queres indicar el rango 

mv archivo{1..N} # donde N=numero final del rango  

en tu caso  archivo{1..12}

 

Entonces, ¿lo hacia yo mal?, yo le pasaba esto por variable "/home/alumno/archivo[1-12]", lo hacia con corchetes.

Jue, 26/05/2016 - 13:12 (Responder a #3)
mcgregor
Imagen de mcgregor
Desconectado/a
se unió: 26/05/16

No, con llaves no me funciona.

Pongo el codigo que interesa:

echo
	echo ----------------------------------------
	echo a - Borrar archivo
	echo ----------------------------------------
	read op

	case $op in
	a)
		contenido=`ls "$papelera" | wc -l`

		if [ $contenido -lt 10 ]
		then
			echo Introduzca el nombre del archivo a borrar, incluida la ruta
			read archivo

			if [ -f "$archivo" ]
			then
				mv $archivo $papelera
				contenido=`ls "$papelera" | wc -l`

				if [ $contenido -ge 10 ]
				then
					clear
					echo
					echo --------------
					echo PAPELERA LLENA
					echo --------------
					echo
				fi
			else
				for file in $archivo
				do
					mv "$file" $papelera
					contenido=`ls "$papelera" | wc -l`

					if [ $contenido -ge 10 ]
					then
						clear
						echo
						echo --------------
						echo PAPELERA LLENA
						echo --------------
						echo
						break
					fi
				done
			fi
		else
			clear
			echo
			echo --------------
			echo PAPELERA LLENA
			echo --------------
			echo
		fi
		;;

Por lo que veo, entra en la primera parte del IF ...

if [ -f "$archivo" ]
			then
				mv $archivo $papelera
				contenido=`ls "$papelera" | wc -l`

				if [ $contenido -ge 10 ]
				then
					clear
					echo
					echo --------------
					echo PAPELERA LLENA
					echo --------------
					echo
				fi

y le pasa el contenido de la variable archivo como un literal, y claro el mv dice que no existe.

Voy a probar quitandole las comillas.

Jue, 26/05/2016 - 13:22 (Responder a #4)
mcgregor
Imagen de mcgregor
Desconectado/a
se unió: 26/05/16

Nada, no funciona, si le pongo /home/alumno/archivo[1-12] solo me mueve el archivo1 y el archivo2 (no entiendo por que, la verdad) y con llaves nada. y poniendole comillas

if [ -f "$archivo" ]
			then
                                #comillas en la variable $archivo
				mv "$archivo" $papelera
				contenido=`ls "$papelera" | wc -l`

				if [ $contenido -ge 10 ]
				then
					clear
					echo
					echo --------------
					echo PAPELERA LLENA
					echo --------------
					echo
				fi

tampoco. crying

Jue, 26/05/2016 - 15:44
caliban
Imagen de caliban
Desconectado/a
moderador
se unió: 14/01/16

intentalo asi 

archivo=/ruta/archivo/file{1..10}
eval mv $archivo   /ruta/destino

 

Jue, 26/05/2016 - 16:40 (Responder a #6)
mcgregor
Imagen de mcgregor
Desconectado/a
se unió: 26/05/16

caliban wrote:

intentalo asi 

archivo=/ruta/archivo/file{1..10}
eval mv $archivo   /ruta/destino

 

¿Te refieres a esto? (ahora mismo no puedo probarlo, en cuanto llegue a casa lo pruebo)

if [ -f "$archivo" ]
then
   eval mv $archivo $papelera
   contenido=`ls "$papelera" | wc -l`

   if [ $contenido -ge 10 ]
   then
      clear
      echo
      echo --------------
      echo PAPELERA LLENA
      echo --------------
      echo
   fi
........

Gracias por la ayuda calibanwink

Lun, 30/05/2016 - 05:27
mcgregor
Imagen de mcgregor
Desconectado/a
se unió: 26/05/16

Nada, no he conseguido hacerlo, si al alguno se le ocurre algo, por favor lo comente.

 

Muchas gracias.

Lun, 30/05/2016 - 12:14
caliban
Imagen de caliban
Desconectado/a
moderador
se unió: 14/01/16

Bien, en principio quizá no capte bien cuando decis  archivo1 archivo2 etc, pero te pongo un ejemplo 

tmp$ mkdir bla
ale@pcale:/tmp$ cd bla
ale@pcale:/tmp/bla$ touch archivo1
ale@pcale:/tmp/bla$ touch archivo2
ale@pcale:/tmp/bla$ touch archivo3
ale@pcale:/tmp/bla$ touch archivo4
ale@pcale:/tmp/bla$ ls
archivo1  archivo2  archivo3  archivo4
ale@pcale:/tmp/bla$ arch=/tmp/bla/archivo{1..4};eval mv $arch /tmp
ale@pcale:/tmp/bla$ cd ../
ale@pcale:/tmp$ ls
archivo1  
archivo2  
archivo3  
archivo4  
___________________________________________________________      
tmp$ destino=/tmp/bla archx=/tmp/archivo{1..4};eval mv $archx $destino
ale@pcale:/tmp$ cd bla
ale@pcale:/tmp/bla$ ls
archivo1  archivo2  archivo3  archivo4

En el ejemplo he creado cuatro archivos en /tmp/bla , y los he movido hacia /tmp, y luego nuevamente hacia /tmp/bla 

Mié, 01/06/2016 - 13:19 (Responder a #9)
mcgregor
Imagen de mcgregor
Desconectado/a
se unió: 26/05/16

caliban wrote:

Bien, en principio quizá no capte bien cuando decis  archivo1 archivo2 etc, pero te pongo un ejemplo 

tmp$ mkdir bla
ale@pcale:/tmp$ cd bla
ale@pcale:/tmp/bla$ touch archivo1
ale@pcale:/tmp/bla$ touch archivo2
ale@pcale:/tmp/bla$ touch archivo3
ale@pcale:/tmp/bla$ touch archivo4
ale@pcale:/tmp/bla$ ls
archivo1  archivo2  archivo3  archivo4
ale@pcale:/tmp/bla$ arch=/tmp/bla/archivo{1..4};eval mv $arch /tmp
ale@pcale:/tmp/bla$ cd ../
ale@pcale:/tmp$ ls
archivo1  
archivo2  
archivo3  
archivo4  
___________________________________________________________      
tmp$ destino=/tmp/bla archx=/tmp/archivo{1..4};eval mv $archx $destino
ale@pcale:/tmp$ cd bla
ale@pcale:/tmp/bla$ ls
archivo1  archivo2  archivo3  archivo4

En el ejemplo he creado cuatro archivos en /tmp/bla , y los he movido hacia /tmp, y luego nuevamente hacia /tmp/bla 

No entiendo muy bien lo que quieres decir (sorry), en el script no me coje "archivo{1..12}" me dice que el archivo no existe.

He leido lo que hace el comando eval, pero no termino de entenderlo. Si eres tan amable de explicarmelo te lo agradeceria.

Mié, 01/06/2016 - 15:24
caliban
Imagen de caliban
Desconectado/a
moderador
se unió: 14/01/16

Tengo una duda ,cuando vos pasas el archivo ¿pones el path completo ? o sea 

/ruta/al/archivo{1..12}

O simplemente estas pasando 

archivo{1..12}

En el segundo caso no te va a funcionar 

En cuanto a eval , evalúa dos veces , algo asi como ejecutar una orden , a continuación la siguiente y devuelve el resultado Te reitero el ejemplo ampliado :

ls |grep archivo
archivo1
archivo2
archivo3
archivo4
archivo5
----------------------------------------------------
modo debug
---------------------------------------------------
ale@pcale:/tmp$ set -vx
---------------------------------------------------
ale@pcale:/tmp$ eval read A ;  mv $A /tmp/bla
eval read A ;  mv $A /tmp/bla
+ eval read A
read A
++ read A
archivo{1..5}
+ mv 'archivo{1..5}' /tmp/bla
mv: no se puede efectuar `stat' sobre 'archivo{1..5}': No existe el fichero o el directorio
ale@pcale:/tmp$ eval read A ;  eval mv $A /tmp/bla
eval read A ;  eval mv $A /tmp/bla
+ eval read A
read A
++ read A
archivo{1..5}
+ eval mv 'archivo{1..5}' /tmp/bla
mv archivo{1..5} /tmp/bla
++ mv archivo1 archivo2 archivo3 archivo4 archivo5 /tmp/bla

Edito :Cometí un error  donde dice 

eval read A ;  eval mv $A /tmp/bla   ←←← INCORRECTO 
Solo debe decir 
 read A ;  eval mv $A /tmp/bla       ←←←←CORRECTO 

 

Mié, 01/06/2016 - 16:33 (Responder a #11)
mcgregor
Imagen de mcgregor
Desconectado/a
se unió: 26/05/16

Le paso la ruta completa, asi:

/home/alumno/archivo[1-12] (no uso las llaves por que no funciona)

Asi, me borra el archivo1 y el archivo2 indecision

Te paso el codigo completo, te invito a que lo pruebes, va rapido.

Otra vez darte las gracias por la ayuda, por que el profesor tampoco sabe como hacerlo crying

clear

if [ ! -d $HOME/papelera ]
then
	mkdir $HOME/papelera
fi

papelera="$HOME/papelera/"
op=a
archivos=0
carpetas=0

until [ $op = x ]
do
	echo
	echo Papelera de Gregorio \(-_-\)
	echo ----------------------------------------
	echo a - Borrar archivo
	echo b - Muestra el contenido de la papelera
	echo c - Recupera un archivo
	echo d - Vacia la papelera
	echo x - Salir
	echo ----------------------------------------
	read op

	case $op in
	a)
		contenido=`ls "$papelera" | wc -l`

		if [ $contenido -lt 10 ]
		then
			echo Introduzca el nombre del archivo a borrar, incluida la ruta
			echo No use espacios en blanco.
			read archivo

			if [ -f "$archivo" ]
			then
				mv $archivo $papelera
				contenido=`ls "$papelera" | wc -l`

				if [ $contenido -ge 10 ]
				then
					clear
					echo
					echo --------------
					echo PAPELERA LLENA
					echo --------------
					echo
				fi
			else
				for file in $archivo
				do
					mv "$file" $papelera
					contenido=`ls "$papelera" | wc -l`

					if [ $contenido -ge 10 ]
					then
						clear
						echo
						echo --------------
						echo PAPELERA LLENA
						echo --------------
						echo
						break
					fi
				done
			fi
		else
			clear
			echo
			echo --------------
			echo PAPELERA LLENA
			echo --------------
			echo
		fi
		;;
	b)
		contenido=`ls "$papelera" | wc -l`

		if [ $contenido -eq 0 ]
		then
			clear
			echo
			echo ---------------
			echo PAPELERA VACIA
			echo ---------------
			echo
		else
			clear
			echo Contenido de la papelera
			echo -------------------------------------------
			ls -lA $papelera
			echo -------------------------------------------
			echo Resumen:

			for fich in $papelera/*
			do
				if [ -f "$fich"  ]
				then
					archivos=`expr $archivos + 1`
				elif [ -d "$fich" ]
				then
					carpetas=`expr $carpetas + 1`
				fi
			done

			echo Carpetas:$carpetas -  Archivos:$archivos
			echo -------------------------------------------
			echo -------------------------------------------
			echo
			carpetas=0
			archivos=0
		fi
		;;
	c)
		echo Introduce el nombre del archivo a recuperar
		read archivo

		if [ -f "$papelera/$archivo" -o -d "$papelera/$archivo"  ]
		then
			archivo="$papelera/$archivo"
			echo Directorio de recuperacion:
			read dirRecu

			if [ -d "$dirRecu" ]
			then
				mv "$archivo" "$dirRecu"
				clear
				echo
				echo ------------------
				echo Archivo recuperado
				echo ------------------
				echo
			else
				clear
				echo
				echo ---------------------------------------
				echo El directorio de recuperacion no existe
				echo ---------------------------------------
				echo
			fi
		else
			clear
			echo
            echo --------------------
            echo El archivo no existe
            echo --------------------
            echo
		fi
		;;
	d)
		echo Desea vaciar la papelera? \(s/n\)
		read vaciar

		if [ $vaciar = s ]
		then
			rm -r $papelera/*
			clear
			echo
			echo ----------------
			echo Papelera vaciada
			echo ----------------
			echo
		fi
		;;
	x)
		echo Saliendo
		break
		;;
	*)
		clear
		echo
		echo ------------------------------
		echo Introduzca una de las opciones
		echo ------------------------------
		echo
	esac
done

Con la opcion a) luego te pide la ruta completa al archivo/s a borrar, con los comodines como * y ? funciona perfectamente.

Primero comprueba si el nombre (incluida la ruta) es un archivo y si no pasa a la otra parte del if.

Mié, 01/06/2016 - 16:50
caliban
Imagen de caliban
Desconectado/a
moderador
se unió: 14/01/16

Pero no tenes que pasarle la ruta con los corchetes []  tenes que usar llaves {}, y además    especificar un rango 

/ruta/al/archivo{1..12}

bash va a expandir el contenido  de las llaves para el rango especificado ! eval hace que prmero expanda y evalue cada archivo y luego  se ejecuta mv 

Mié, 01/06/2016 - 18:01
caliban
Imagen de caliban
Desconectado/a
moderador
se unió: 14/01/16

Se me ocurre que esta parte ,tengas que modificar :

else
				for file in $archivo
				do
					mv "$file" $papelera
					contenido=`ls "$papelera" | wc -l`

De este modo :

for file in $(eval echo $archivo)
     do 
           mv $file $ papelera 

 

Lun, 06/06/2016 - 04:19
mcgregor
Imagen de mcgregor
Desconectado/a
se unió: 26/05/16

He conseguido que funcione con este tipo de archivos (archivo1 ... 12), siempre y cuando  no tengan espacios en blanco en el nombre (ya se que no es recomendable), es decir, con archivos con un nombre como archivo 1, archivo 2, etc... no me funciona, en fin .... supongo que son limitaciones que tengo que aceptar.

He usado el eval como me has dicho (for file in $(eval echo $archivo)), lo voy a dejar asi, por que no creo que pueda hacer mucho mas.

Muchisimas gracias por la ayuda Caliban, es agradable que haya gente como tu dispuesta a ayudar a los demas, muchas gracias. yes

Lun, 06/06/2016 - 12:47
caliban
Imagen de caliban
Desconectado/a
moderador
se unió: 14/01/16

Y si intentas 

eval mv 'archivo\ {1..12}'

El asunto, cuando estas intentando hacer este tipo de scripts y no conoces bien los comandos y las alternativas, es hacer ensayos con pequeñas partes y luego las amplias( y finalmente las integras entre si)  en  este caso el paso previo es entender como mover archivos que contienen un espacio en sus nombres, cuando te funcione pasas a asignarlos a variables  y luego con   eval  y todo lo demás.

/tmp es un buen lugar donde crear directorios y hacer ensayos, finalmente luego de reiniciar no te quedara basura en el sistema .