'é um diretório' ao tentar passar o nome do diretório para a função

5

No meu script bash, eu uso find para obter os nomes das pastas por curinga:

for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard});
do
  stuff=doStuff ${i}
done

doStuff() {
  echo ${1}
  return ${1}'/hello';
}

O problema é que, quando faço isso, recebo o seguinte erro (digamos que $ {i} corresponde a 'home / me / my_directory'):

line 111: '/home/me/my_directory': is a directory. 

(linha 111 é a linha com 'doStuff')

Eu tentei fazer isso sem sucesso:

for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard});
do
  stuff=doStuff "${i}"
done

Aparentemente, é porque o programa está tentando executar o diretório, mas eu quero apenas como uma string que eu possa manipular.

    
por user2205763 22.05.2014 / 21:08

3 respostas

7

Citações e substituição de comandos são seus problemas aqui.

O problema específico em que você está se deparando é porque o shell está tentando executar um comando chamado /home/me/my_directory com a variável de ambiente stuff=doStuff .
O que você realmente quer (se eu estiver interpretando corretamente) é executar doStuff com o valor de $i como um argumento, atribuindo a saída à variável stuff . A maneira de fazer isso é colocar o comando em $() . Por exemplo:

stuff="$(doStuff "$i")"

Aviso Como eu também coloco aspas em torno de tudo. Isso evita que o shell divida as coisas que você não quer que ele divida (isso transformará um único argumento de /foo/bar baz em /foo/bar e baz ).

Além disso, a saída da sua função é o que é usado como valor de retorno, não return .

Como você deve usar mais aspas, você também deve adicioná-las a todo o resto. Aqui está uma versão completa do seu script:

doStuff() {
  echo "${1}" >&2
  printf '%s/hello' "$1";
}

IFS=$'\n'
for i in $(find "${directory}" -mindepth 1 -type d -name "${wildcard}");
do
  stuff="$(doStuff "${i}")"
done

Você tem que colocar a definição de função antes de tentar usá-la. O shell não é analisado como programas compilados, onde ele passa pelo arquivo várias vezes. É de cima para baixo.
Eu também modifiquei doStuff para enviar o echo para STDERR onde ele será mostrado no terminal, e então o printf envia para STDOUT onde ele será capturado na variável stuff .

Observe que isso ainda terá um problema se algum dos seus diretórios contiver uma nova linha. No entanto, isso é uma limitação do shell. O único caractere que um caminho de arquivo não pode conter é um caractere NULL ( %code% ). No entanto, o bash e outros shells não podem armazenar um caractere NULL em uma string (não todos, mas muitos. Eu sei que o zsh can), então você não pode usá-lo como um delimitador.

    
por 22.05.2014 / 21:31
3

Esse é um bom esforço, mas mostra que você está tentando escrever bash como se fosse uma linguagem de programação, quando na verdade é uma linguagem de script simples. O problema com sua construção stuff=doStuff arg é que para bash isso não significa o que você acha que significa. Para bash , stuff=doStuff é uma atribuição de variável e arg é um comando. Eu sugiro que você leia os dois links a seguir:

Uma versão funcional de algo semelhante ao que você teria seria

doStuff () {
    echo "$1/hello"
}

stuff=$(doStuff "$i")
    
por 22.05.2014 / 21:32
1

A linha que indica o erro não faz o que você pensa:

Primeiro, ele configura o material da variável de ambiente para a string "doStuff" e, em seguida, tenta executar $ {i} como um comando. E como $ {i} é um diretório, que falha com a mensagem de erro fornecida.

    
por 22.05.2014 / 21:32