Bash copia archivos de múltiples directorios a múltiples directorios de respaldo correspondientes

Bash copia archivos de múltiples directorios a múltiples directorios de respaldo correspondientes

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/*.zipel 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 xargspá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 forbucle 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é diren caso de que sustituyas un nombre con espacios más o menos. Cité dos veces $dpor la misma razón ymás.
  • Si *.zipson archivos, entonces no los necesita -r.

Alternativamente la forlí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 que cdno 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 $des un directorio.
  • Intentamos crear el directorio de destino (en caso de que no exista).
  • Procederemos cpsólo si el directorio de destino existe.
  • Usamosdoble guiónen caso de que $dcomience con un guión.

Posibles problemas:

  • "$d"/*.zippuede 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"/*.zipno 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.

información relacionada