Escopo das variáveis ao chamar a função do find

3

Em um script bash eu defino uma função que é chamada de find . O problema é que o escopo das variáveis não se estende à função. Como eu acesso variáveis da função? Aqui está um exemplo:

variable="Filename:"

myfunction() {
    echo $variable $1
}

export -f myfunction

find . -type f -exec bash -c 'myfunction "{}"' \;

Isso produzirá nomes de arquivos, mas sem a string "Filename:".

Existe, talvez, uma maneira melhor de chamar uma função de find , de modo que ela seja chamada para todos os arquivos que find encontra e as variáveis ainda estão definidas?

    
por DustByte 27.08.2013 / 16:25

4 respostas

3

Você pode declarar variable como uma variável de ambiente, ou seja,

export variable="Filename:"
    
por 27.08.2013 / 16:35
6

Não é uma resposta à sua pergunta, mas não faça :

find . -type f -exec bash -c 'myfunction "{}"' \;

Além do fato de que não é portátil, também é muito perigoso, porque os nomes dos arquivos acabam sendo interpretados por bash como código shell. Considere, por exemplo, o que aconteceria se houvesse um arquivo chamado $(rm -rf ~) lá embaixo. Escreva:

find . -type f -exec bash -c 'myfunction "$1"' find+bash {} \;

Ou melhor ainda (para evitar a execução de um bash por arquivo):

find . -type f -exec bash -c 'for file do
  myfunction "$file"; done' find+bash {} +

Agora, uma resposta à sua pergunta sobre o assunto:

Você pode fazer:

{ find . -type f -exec printf '%s
find . -type f -exec bash -c 'myfunction "{}"' \;
' {} + | while IFS= read -ru3 -d '' file; do myfunction "$file"; done 3<&0 <&4 4<&-; } 4<&0

Dessa forma, você está chamando myfunction dentro do shell bash atual, portanto, não é necessário exportar myfunction ou executar mais bash shells.

Se o seu find suportar o predicado -print0 (como GNU, busybox e alguns BSDs find s), você poderá substituir -exec printf '%s-print0' {} + por %code%

    
por 27.08.2013 / 17:00
1

Eu faria como segue

#!/bin/bash

myfunction() {
    local var="Filename: "
    local file=$1 
        echo "$var" "$file"
    }

export -f myfunction
    find . -type f -exec bash -c 'myfunction {}' \;

Declare vars como local e passe '{}' para a função que é $1 primeiro parâmetro posicional.

    
por 27.08.2013 / 16:49
1

Quando você atribui a uma variável, ela começa como uma variável do shell. Para obter uma variável de ambiente que é passada para subprocessos, você precisa exportá-la.

variable="Filename:"
export variable

Você pode colocar a atribuição na mesma linha que export : export variable="Filename:" .

A variável será visível para os shells iniciados por find , mas não para as funções. No bash, você também pode exportar funções. Esta possibilidade não está presente no ksh, no traço e em outros shells que são frequentemente usados como sh porque são mais rápidos e mais finos.

export -f myfunction    # bash only

Nunca use {} dentro de uma string em find -exec … (ou xargs … ), a menos que você saiba que seus nomes de arquivo são alfanuméricos. Se houver algum caractere especial nos nomes dos arquivos, eles serão analisados como tal pelo shell interno. Em vez disso, passe os nomes dos arquivos na linha de comando do shell.

find . -type f -exec bash -c 'for x; do myfunction "$x"; done' _ {} +

Com shells diferentes de bash, defina a função no shell interno ou apenas coloque seu código diretamente.

Como alternativa, no bash, você pode usar globalização recursiva em vez de localizar. Cuidado com o fato de que o bash atravessa links simbólicos para diretórios.

variable="Filename:"
myfunction () { … }
shopt -s globstar dotglob
for x in **/*; do
  if [[ -f $x ]]; then myfunction "$x"; fi
done
    
por 28.08.2013 / 03:26