arquivos cksum usando string variável substituída como um padrão

1

Posso evitar eval no exemplo abaixo ou não há outra maneira? A lista de arquivos na variável é dinâmica, e eu quero cksum todos eles. Existem muitos outros arquivos no diretório, mas eles devem ser ignorados.

$ Z="file1 file4"
$ echo ${Z//\ /,}
file1,file4
$ echo {${Z//\ /,}}
{file1,file4}
$ cksum {file1,file4}
927007485 136284 file1
2748059092 136286 file4
$ cksum {${Z//\ /,}}
cksum: {file1,file4}: No such file or directory
$ eval cksum {${Z//\ /,}}
927007485 136284 file1
2748059092 136286 file4
    
por Chris 16.04.2018 / 15:06

2 respostas

3

Usando uma matriz em vez de uma string:

files=( file1 file2 "filename with spaces" file50 "*my* file" )

cksum "${files[@]}"

Observe que todas as aspas duplas acima são importantes, especialmente se você tiver nomes de arquivos com espaços ou caracteres de globalização de nomes de arquivo neles.

    
por 16.04.2018 / 15:14
1

Para explicar por que cksum {${Z//\ /,}} não funcionou como esperado:

  1. de acordo com a ordem de substituições / expansões , ocorre a expansão de chave antes substituições de parâmetro
  2. no entanto, está documentado que "Para evitar conflitos com a expansão de parâmetros , a string '$ {' não é considerada elegível para expansão de chaves. " - então o bash não executa a expansão de chaves aqui.
  3. , em seguida, o shell finalmente chega à substituição de parâmetro e o comando é expandido para cksum {file1,file4}
  4. o shell não volta e refaz a lista de expansões, então não obtemos mais expansão de brace: ficamos com a única palavra "{file1, file4}"
  5. e não existe tal arquivo.

Quando você introduz eval no mix, você está explicitamente pedindo ao shell para percorrer a lista de expansões mais uma vez. Agora podemos obter a expansão de chaves no comando cksum {file1,file4} e você obtém as somas de verificação para esses 2 arquivos.

    
por 16.04.2018 / 18:46