¿Copiar varios archivos y crear los directorios de destino al mismo tiempo?

¿Copiar varios archivos y crear los directorios de destino al mismo tiempo?

Yo leo¿Cómo puedo copiar un archivo y crear los directorios de destino al mismo tiempo?

Pero la solución allí sólo funciona si quieres copiarunoarchivo.

¿Cómo puedo copiar varios archivos en un directorio que aún no existe y crearlo automáticamente con un comando?

Por ejemplo:

cd /tmp/
mkdir a/
cd a/
touch x1 x2
cp --magic * ../b/c/d/

entonces al final los dos archivos x1quedan x2ordenados así:

/tmp/b/c/d/x1
/tmp/b/c/d/x2

Respuesta1

Usar:

$ copy() { mkdir -p -- "${@: -1}" && cp -- "$@" ; }
$ copy * ../b/c/d/

Nota: funciona con bash, ksh93 y zsh.

"${@: -1}"corresponde a la ${parameter:offset}forma: todos los parámetros comenzando en el desplazamiento. El desplazamiento -1 corresponde al último parámetro, ya que los desplazamientos negativos cuentan desde el final. El espacio es necesario, sino sería la ${parameter:-word}forma. Consulte el manual de bash para obtener más información.

"$@"se expande a la lista de parámetros, que es lo que se busca cp.

Nota 2: según lo sugerido por mikeserv, puedes usar

eval 'mkdir -p -- "${'"$#"'}"'

que es más portátil (POSIX), en lugar de

mkdir -p -- "${@: -1}"

En cuanto al rendimiento, la evalsolución es mucho más rápida con bash 4.3.30, pero la otra solución es más rápida con ksh 93u+ y zsh 5.0.6 (ksh93 y zsh son mucho más rápidos que bash en ambos casos); y dash 5.7 con la evalsolución (el otro no es compatible) es un poco más rápido que ksh93 con la "${@: -1}"solución. Entonces, dependiendo de su caso (script, uso interactivo, soporte para características específicas de Shell, etc.), haga su elección... Sin embargo, tenga en cuenta que en el contexto de cp(lo cual tomará la mayor parte del tiempo), estas diferencias de rendimiento no desaparecerán. No se nota.

El script que utilicé para la prueba:

i=50000
while [ $i -ne 0 ];
do
  # : "${@: -1}"
  eval ': "${'"$#"'}"'
  i=$((i-1))
done

(comente la evallínea y descomente la línea anterior para la otra solución), llamada con:

time sh ./tst `seq 1000`
time bash ./tst `seq 1000`
time ksh93 ./tst `seq 1000`
time zsh ./tst `seq 1000`

Respuesta2

¡Tuve el mismo problema y solía tarresolverlo! Al igual que:

tmpfile=/tmp/myfile.tar
files="/some/folder/file1.txt /some/other/folder/file2.txt"
targetfolder=/home/you/somefolder

tar --file="$tmpfile" "$files"​
tar --extract --file="$tmpfile" --directory="$targetfolder"

En este caso, tarcreará automáticamente todas las (sub)carpetas. Mejor,

nabí

información relacionada