Tengo la siguiente estructura de archivos:
- /inicio/datos/C01/dir_wwe_346/archivo1.txt pic.jpg aleatorio.sh
- /inicio/datos/C02/dir_wwe_644/archivo1.txt pic.jpg aleatorio.sh
- /inicio/datos/C03/dir_wwe_324/archivo1.txt pic.jpg aleatorio.sh
Quiero que sean así:
- inicio/datos/C01/archivo1.txt pic.jpg aleatorio.sh
- inicio/datos/C02/archivo1.txt pic.jpg aleatorio.sh
- inicio/datos/C03/archivo1.txt pic.jpg aleatorio.sh
Básicamente se trata de mover varios archivos un directorio hacia arriba. Probé este script sin éxito:
#!/bin/bash for i in */ do cd i/*/ mv * ../ done
Después de publicar esto (pero antes de leer la respuesta de Grawity a continuación), me di cuenta de que no usé la expansión de variables adecuada y ejecuté esto:
#!/bin/bash for i in */ do cd ${i}*wwe* mv * ../ done
El script mueve todos los subdirectorios a la carpeta de datos, por lo que termino con esto:
- /hogar/C01/dir_wwe_346/archivo1.txt pic.jpg aleatorio.sh
- /hogar/C02/dir_wwe_644/archivo1.txt pic.jpg aleatorio.sh
/hogar/C03/dir_wwe_324/archivo1.txt pic.jpg aleatorio.sh
¿Qué estoy haciendo mal?
PD. Edité la publicación para que revele el proceso por el que pasé y para que las respuestas tengan más sentido para los recién llegados que podrían beneficiarse de ellas. Gracias gracity, aprendí algo nuevo. Acabo de empezar a aprender bash hace una semana y siento que estoy progresando.
Respuesta1
Las variables sólo se reconocen y amplían con el
$
prefijo. Si el bucle define una variable 'i', debes usar$i
cuando quieras su valor:for i in */; do cd $i/*/
El "directorio actual" abarca todo el proceso y no restablece automáticamente cada iteración del bucle. Luego deberá regresar manualmente al directorio principal:
cd $i/*/; mv * ../; cd ../../
o utilice una "subshell" para determinar el alcance del cambio de directorio:
(cd $i/*/; mv * ../)
No estás haciendo ninguna comprobación de errores. Si
cd
alguna vez falla, lo siguientemv
puede causar cosas desagradables. Combine comandos usando&&
o haga lo contrario, verifique y use|| exit
(o|| break
), lo que se vea mejor:for i in */; do cd $i/*/ && { mv * ../; cd ../../ } done for i in */; do cd $i/*/ || exit mv * ../ cd ../../ done for i in */; do (cd $i/*/ && mv * ../) done
Mejora: puede mover el comodín del subdirectorio a
mv
, lo que le permitirá funcionar incluso en caso de que haya varios subdirectorios:cd $i/ || exit mv */* . cd ../
Mejora: podrías hacer esto sin necesidad
cd
de:mv $i/*/* $i/