Copia vários arquivos e cria os diretórios de destino ao mesmo tempo?

2

Eu leio Como posso copiar um arquivo e criar os diretórios de destino ao mesmo tempo?

Mas a solução só funciona se você quiser copiar um arquivo.

Como eu copiaria vários arquivos em um diretório, que ainda não existe e o criaria automaticamente com um comando?

por exemplo:

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

No final, os dois arquivos x1 e x2 são ordenados assim:

/tmp/b/c/d/x1
/tmp/b/c/d/x2
    
por rubo77 09.10.2014 / 00:48

1 resposta

2

Uso:

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

Nota: funciona com o bash, ksh93 e zsh.

"${@: -1}" corresponde ao ${parameter:offset} form: todos os parâmetros que começam no deslocamento. O offset -1 corresponde ao último parâmetro, já que os offsets negativos contam a partir do final. O espaço é necessário, caso contrário, seria a forma ${parameter:-word} . Veja o manual bash para mais informações.

"$@" expande para a lista de parâmetros, o que é desejado para cp .

Nota 2: Como sugerido por mikeserv, você pode usar

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

que é mais portátil (POSIX), em vez de

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

Em relação ao desempenho, a solução eval é muito mais rápida com o bash 4.3.30, mas a outra solução é mais rápida com o ksh 93u + e o zsh 5.0.6 (o ksh93 e o zsh são muito mais rápidos que o bash nos dois casos); e o dash 5.7 com a solução eval (o outro não é suportado) é um pouco mais rápido que o ksh93 com a solução "${@: -1}" . Portanto, dependendo do seu caso (script, uso interativo, suporte para recursos de shell específicos, etc.), faça sua escolha ... Observe, entretanto, que no contexto de cp (que levará a maior parte do tempo), esse desempenho diferenças não serão perceptíveis.

O script que usei para o teste:

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

(comente a linha eval e descomente a linha anterior para a outra solução), chamada com:

time sh ./tst 'seq 1000'
time bash ./tst 'seq 1000'
time ksh93 ./tst 'seq 1000'
time zsh ./tst 'seq 1000'
    
por 09.10.2014 / 01:01

Tags