Tengo varios directorios { dir1,dir2,dir3,dir4
} en una máquina Linux.
Hay varios archivos en cada directorio (con la misma extensión, digamos .zip) de los que quiero hacer una copia de seguridad en los directorios correspondientes { dir1-bck,dir2-bck,dir3-bck,dir4-bck
}. No necesito hacer una copia de seguridad de toda la carpeta, solo de unos pocos archivos en cada una.
¿Cómo haría para copiar los archivos desde dir1/*.zip
el archivo dir1-bck
. . . para obtener una lista de directorios proporcionados. Actualmente estoy usando:
cp -r src/dir1/*.zip dest/dir1-bck/
cp -r src/dir2/*.zip dest/dir2-bck/
cp -r src/dir3/*.zip dest/dir3-bck/
cp -r src/dir4/*.zip dest/dir4-bck/
Lo cual funciona pero tiene un gran margen de mejora.
Al revisar la xargs
página de manual y publicaciones similares en el foro, creo que es la herramienta para este trabajo, pero parece que no puedo hacerlo bien.
Respuesta1
Probablemente un for
bucle será perfecto. La forma exacta depende de cómo se nombren estos directorios. Puede ser:
cd src || exit 1
for d in "dir"{1..4}; do
cp -r "$d"/*.zip "../dest/$d-bck/"
done
Notas:
- Es bueno trabajar desde dentro
src
(cd src
), por lo que la variable contiene una cadena que se puede usar en la ruta de destino sin procesamiento adicional. La ruta de destino se ajustó anteponiendo../
en este caso, pero en general puede ser como"/full/path/to/dest/$d-bck/"
. - Cité
dir
en caso de que sustituyas un nombre con espacios más o menos. Cité dos veces$d
por la misma razón ymás. - Si
*.zip
son archivos, entonces no los necesita-r
.
Alternativamente la for
línea podría ser:
for d in dir1 dir2 dir3 dir4; do
lo cual sería útil si necesita especificar algunos directorios con nombres arbitrarios. O incluso:
for d in *; do
Se pueden hacer pocas mejoras, como esta:
( cd src || exit 1
for d in *; do
dst="../dest/$d-bck/"
[ -d "$d" ] && mkdir -p "$dst" && cp -- "$d"/*.zip "$dst"
done )
Las mejoras:
- Todo el código se ejecuta en un subshell (
(…)
), por lo quecd
no afectará al shell actual incluso si pega el código en una terminal. Si tuviera que ser un script independiente (ejecutado, sin fuente), entonces la subcapa sería irrelevante. - Comprobamos si
$d
es un directorio. - Intentamos crear el directorio de destino (en caso de que no exista).
- Procederemos
cp
sólo si el directorio de destino existe. - Usamosdoble guiónen caso de que
$d
comience con un guión.
Posibles problemas:
"$d"/*.zip
puede expandirse a demasiados elementos (Argument list too long
). Sus comandos originales tienen "defectos" de la misma manera. Si hay "sólo unos pocos archivos en cada directorio", entonces esto no debería ser un problema."$d"/*.zip
no puede expandirse (*
permanecerá literal). No debería causar ningún daño, aun así el directorio de destino se creará de antemano. Es posible que se desee una lógica adicional para suprimir la creación de directorios en tal caso.- El estado de salida de todo el fragmento depende únicamente del último
[ … && mkdir … && cp …
. Necesita lógica adicional para que los problemas anteriores afecten el estado de salida.