No meu script bash, 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} corresponda 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.
Comentários
Resposta
Citações e substituição de comandos são seus problemas aqui.
O problema específico que você está enfrentando é 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 deseja (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 é envolver seu comando em $()
. Por exemplo:
stuff="$(doStuff "$i")"
Observe como também coloco aspas em tudo. Isso evita que o shell divida coisas que você não deseja (ele transforma um único argumento de /foo/bar baz
em /foo/bar
e baz
).
Além disso, a saída de sua função é o que é usado como o valor de retorno, não return
.
Como você deve usar mais aspas, 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ê deve colocar a definição da função antes de tentar usá-la. O shell não é analisado como programas compilados, onde percorre o arquivo várias vezes. É de cima para baixo.
Eu também modifiquei doStuff
para enviar o echo
para STDERR onde será mostrado no terminal e, em seguida, printf
envia para STDOUT, onde será capturado na variável stuff
.
Observe que isso ainda terá um problema se algum de seus diretórios contiver uma nova linha. No entanto, esta é uma limitação do shell. O único caractere que um caminho de arquivo não pode conter é um caractere NULL (\0
). No entanto, bash e outros shells não podem armazenar um caractere NULL em uma string (nem todos, mas muitos. Eu sei que zsh pode), então você pode ” use-o como um delimitador.
Comentários
- Só queria adicionar isso se você tiver espaço antes / depois
=
, ele bagunça. por exemplo. MY_VAR = ' / some / path ' é válido, mas MY_VAR = ' / some / caminho ' ou MY_VAR = ' / some / path ' não é
Resposta
É 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ê pensa que significa. Para bash
, stuff=doStuff
é uma atribuição de variável e arg
é um comando. Sugiro que você leia os dois links a seguir:
- Como posso armazenar o valor de retorno e / ou a saída de um comando em uma variável?
- Como retorno uma string (ou número grande ou número negativo) de uma função? “return” só me permite dar um número de 0 a 255.
Uma versão funcional de algo semelhante ao que você tem seria
doStuff () { echo "$1/hello" } stuff=$(doStuff "$i")
Resposta
A linha que apresenta o erro não faz o que você pensa:
Primeiro, ele define a variável de ambiente stuff para a string “doStuff” e, em seguida, tenta executar $ {i} como um comando. E como $ {i} é um diretório, isso falha com a mensagem de erro fornecida.
find "${directory}" -mindepth 1 -type d -name "${wildcard}" -print0 | xargs -0 doStuff
//a wrong bash line comment
em vez de#a correct bash line comment