Como você suspeitava, ele tinha algo a ver com a sintaxe, mas eu também encontrei alguns outros problemas, e surgiu uma versão que simplesmente descartou o uso de xargs
em favor de um for
loop:
#!/bin/bash
U3=/home/user3/
NF1=/home/user3/mynewfile
File=(grades mynewfile mynewfile1 mynewfile2)
mkdir -p /home/user3/{CIT/{tests,grades},MyStuff/{Tests,Labs},NOS};
echo /etc/hosts.allow > $NF1;
for i in "${File[@]}"; do
cp $NF1 $U3/$i
done
cp $NF1 $U3/CIT/grades/${File[2]}
-
mkdir
linha foi simplificada para descartar as barras finais desnecessárias,mkdir
ainda cria diretórios com barra final ou não, portanto não há necessidade de mais digitação
As razões para o restante das alterações:
Barra redundante
Em primeiro lugar, ao testar algumas linhas do código original:
$ U3=/home/user3/
$ File=(grades mynewfile mynewfile1 mynewfile2)
$ echo $U3/CIT/grades/${File[2]}
/home/user3//CIT/grades/mynewfile1
O caminho salvo em $U3
foi definido com uma barra final, então a linha $U3/CIT/grades/${File[2]}
também possui uma barra após $U3
, fazendo com que o bash a expanda para /home/user3//CIT/grades/mynewfile1
, isso é um problema porque% de barra dupla//
não é o mesmo que /
, cp
por exemplo pode reclamar no such file or directory
.
Portanto, se você quis dizer uma barra simples /
, o método recomendado é definir apenas $U3
para não ter nenhuma barra final:
$ U3=/home/user3
$ File=(grades mynewfile mynewfile1 mynewfile2)
$ echo $U3/CIT/tests/${File[2]}
/home/user3/CIT/tests/mynewfile1
Portanto, isso agora resulta em um caminho adequado, sem barras redundantes.
Expansão de chave incorreta
Com isso corrigido, o próximo bug foi:
$ echo $U3/CIT/tests/${File[*]}
/home/user3/CIT/tests/grades mynewfile mynewfile1 mynewfile2
Suponho que você pretendia expandir os nomes dos arquivos na matriz File
, usando /home/user3/CIT/tests
como um prefixo comum, como essa expansão de chave com vírgulas:
$ echo tweedle{dum,dee}
tweedledum tweedledee
Nesta forma de expansão de chave
- uma string fica bem ao lado da chave
{
antes ou depois de}
ou de ambos, o que você fez corretamente - mas uma
word
, comma,
outra palavra é usada, etc - no entanto, você coloca um
${File[*]}
, eu ainda não vi funcionar com o conteúdo da matriz dessa maneira
Em vez disso, para produzir uma lista feita combinando a mesma palavra ou string inicial comum ( $U3
) mais outra parte que seja diferente baseada em uma matriz ( $File
), eu recomendo um for
loop:
$ for i in "${File[@]}"; do
> echo $U3/$i
> done
Observe que você não digita >
, bash automaticamente fornece isso para indicar continuação de linha. Em um script você acabou de ter:
for i in "${File[@]}"; do
echo $U3/$i
done
O resultado é sempre
/home/user3/grades
/home/user3/mynewfile
/home/user3/mynewfile1
/home/user3/mynewfile2
- em
for i in "${File[@]}"; do
, a cotação ("
), mais@
é importante para ter o loopfor
entendendo corretamente cada nome de arquivo em$File
array como argumentos separados.
Teste
Por fim, o objetivo é copiar um único arquivo, referenciado pela variável $NF1
, para vários locais, definidos pela expansão de $U3
plus $File
array mais $U3/CIT/tests/${File[2]}
A melhor prática para fazer um teste com echo e o comando que você pretende executar, neste caso cp
, para que você possa ver o que será executado, a menos que queira usar set
. Então, primeiro para o nosso teste:
$ NF1=/home/user3/mynewfile
Então
$ for i in "${File[@]}"; do
> echo cp $NF1 $U3/$i
> done
cp /home/user3/mynewfile /home/user3/grades
cp /home/user3/mynewfile /home/user3/mynewfile
cp /home/user3/mynewfile /home/user3/mynewfile1
cp /home/user3/mynewfile /home/user3/mynewfile2
Além disso, parece que você deseja copiar para $U3/CIT/grades/${File[2]}
, para que não seja esquecido, mas adicione-o como uma linha adicional:
$ echo cp $NF1 $U3/CIT/grades/${File[2]}
cp /home/user3/mynewfile /home/user3/CIT/grades/mynewfile1
- tudo ecoa os comandos
cp
que seriam executados - pode ser reescrito para direcionar os argumentos para usar
xargs
semelhante ao seu código original, mas isso realmente envolve mais digitação, então evitamos
Portanto, basta remover o echo
neste exemplo de texto para criar a versão final do código.