Por que esses valores não são anexados corretamente quando anexados ao pipeline? [duplicado]

1

Eu tenho um script bash (visto aqui ) que estou usando para classificar um lista de arquivos em subdiretórios por nome de arquivo.

Este script anexa arquivos classificados em hooks/pre-relevant/ , em seguida, arquivos denominados hooks/pre-relevant , em seguida, arquivos nomeados hooks/relevant e arquivos classificados em hooks/relevant/ , usando a função append_hook abaixo:

hooks=()

# Run a hook script, if it's executable, with the input from this invocation
append_hook () {
  if [[ -f "$1" && -x "$1" ]]; then
    hooks+=("$1")
  fi
}

Estou testando com essa estrutura de diretórios:

testing-range/plugins/
|-- bar
|   '-- hooks
|       |-- irrelevant
|       |-- only-one
|       '-- relevant
|-- dickory
|   '-- hooks
|       '-- pre-relevant
|-- doc
|   '-- hooks
|       |-- perl-envsubst
|       '-- relevant
|           |-- 00
|           '-- 20
|
|-- factory
|   '-- hooks
|       '-- relevant
'-- hickory
    '-- hooks
        |-- pre-relevant
        |   '-- 30
        '-- relevant
            '-- 10

Quando uso este código de matriz de várias etapas para anexar os arquivos:

append_numbered_hooks () {
  # Gather every file into an array, prefixing each item with the
  # filename of the script (its position in sort order)
  local filelist=()
  for hook in "$PLUSHU_ROOT"/plugins/*/hooks/"$hookname"/*; do
    filelist+=("${hook##*/}/$hook")
  done

  # Sort the array numerically
  printf '%s
hickory/hooks/pre-relevant/30
dickory/hooks/pre-relevant
bar/hooks/relevant
factory/hooks/relevant
doc/hooks/relevant/00
doc/hooks/relevant/20
hickory/hooks/relevant/10
' "${filelist[@]}" | sort -nz | IFS= read -rd '' -a filelist # Append each script in sorted order for hookline in "${filelist[@]}"; do append_hook "${hookline#*/}" done }

Eu obtenho quase a saída correta:

append_numbered_hooks () {
  for hook in "$PLUSHU_ROOT"/plugins/*/hooks/"$1"/*; do
    printf '%s
dickory/hooks/pre-relevant
bar/hooks/relevant
factory/hooks/relevant
' "${hook##*/}/$hook" done | sort -nz | while IFS= read -rd '' hookline; do append_hook "${hookline#*/}" done }

No entanto, quando eu adiciono os arquivos usando este pipeline mais simples:

hickory/hooks/pre-relevant/30
dickory/hooks/pre-relevant
bar/hooks/relevant
factory/hooks/relevant
doc/hooks/relevant/00
hickory/hooks/relevant/10
doc/hooks/relevant/20

Os arquivos numerados não aparecem em um loop "$ {hooks [@]}":

hooks=()

# Run a hook script, if it's executable, with the input from this invocation
append_hook () {
  if [[ -f "$1" && -x "$1" ]]; then
    hooks+=("$1")
  fi
}

O que está acontecendo? Os valores corretos devem ser:

testing-range/plugins/
|-- bar
|   '-- hooks
|       |-- irrelevant
|       |-- only-one
|       '-- relevant
|-- dickory
|   '-- hooks
|       '-- pre-relevant
|-- doc
|   '-- hooks
|       |-- perl-envsubst
|       '-- relevant
|           |-- 00
|           '-- 20
|
|-- factory
|   '-- hooks
|       '-- relevant
'-- hickory
    '-- hooks
        |-- pre-relevant
        |   '-- 30
        '-- relevant
            '-- 10
    
por Stuart P. Bentley 13.08.2014 / 14:56

1 resposta

6

Em link

Each command in a pipeline is executed in its own subshell

Então, você está alterando uma variável em um subshell. Quando a subcamada sai, essas alterações desaparecem.

Você pode encontrar substituições de processos úteis.

append_numbered_hooks () {
  while IFS= read -rd '' hookline; do
    append_hook "${hookline#*/}"
  done < <(
    for hook in "$PLUSHU_ROOT"/plugins/*/hooks/"$1"/*; do
      printf '%s
append_numbered_hooks () {
  while IFS= read -rd '' hookline; do
    append_hook "${hookline#*/}"
  done < <(
    for hook in "$PLUSHU_ROOT"/plugins/*/hooks/"$1"/*; do
      printf '%s%pre%' "${hook##*/}/$hook"
    done | 
    sort -nz
  )
}
' "${hook##*/}/$hook" done | sort -nz ) }
    
por 13.08.2014 / 14:59

Tags