Como posso usar uma função que lê uma variável?

6
 #!/bin/bash

 declare -a a=('ls')

 var=0

 while [ -n "${a[$var]}" ]
 do
     var='expr $var + 1'
 done

 Pdir(){
     if[ "'stat -c %F ${a[$i]}'" = "directory" ]
     then
         echo "     __ "
         echo "/---/  |"
         echo "|  d   |"
         echo "--------"
         echo "${a[$i]}"
     else
         echo "nope"
     fi
 }

 for((i=0; i < var ; i++))
 do
         Pdir($i)
 done

Este é o meu código. O que eu quero fazer é quando eu encontrar o diretório e depois imprimir:

     __
/---/  |
|   d  |
--------
"filename"
    
por SeHoon 10.06.2017 / 13:04

2 respostas

12

Sua chamada de função está errada:

Pdir($i)        # this is wrong

No Bash, você chama funções assim como invocaria executáveis binários, escrevendo seu nome como comando e colocando todos os argumentos por trás, separados por espaços e não entre colchetes:

Pdir $i         # this is correct, but not good

Note que você deve quase sempre colocar as variáveis entre aspas duplas, para evitar que elas sejam divididas e interpretadas como múltiplos argumentos se contiverem espaços, então a melhor maneira de escrevê-las seria:

Pdir "$i"       # this is how you do it

Outro pequeno erro é que você precisa de um espaço entre o teste if e o teste [ .

Você também deve citar a variável novamente e é recomendável usar a sintaxe de substituição de comando $(...) mais moderna em vez de '...' . Observe que as aspas duplas dentro de chaves de substituição de comandos são permitidas mesmo se a substituição em si estiver entre aspas duplas.

if [ "$(stat -c %F "${a[$i]}")" = "directory" ]

E, em vez de interpretar a saída de ls ( Por que não analisam ls ? ), é melhor obter uma matriz de arquivos e diretórios no diretório atual, por exemplo usando um glob de shell :

a=(*)

Observe que, por padrão, isso retorna apenas arquivos não ocultos, isto é, tudo que não inicia com um ponto. Para também listar arquivos e diretórios ocultos, ative a opção dotglob shell dentro do seu script uma vez primeiro:

shopt -s dotglob
a=(*)
    
por Byte Commander 10.06.2017 / 13:31
8

Você pode usar o shell glob */ para corresponder apenas aos diretórios - eliminando assim a necessidade de verificar o diretório separadamente:

a=(*/)

Seu primeiro loop é desnecessário - tudo o que ele faz é contar os elementos no array, que você pode obter usando ${#a[@]}

Em qualquer caso, você não precisa realmente saber o número de elementos para fazer um loop sobre eles - você pode usar

for i in "${a[@]}"; do
  Pdir "$i"
done

Também printf é melhor que echo . Então

#!/bin/bash

Pdir(){
  printf '%s\n%s\n%s\n%s\n' \
  "     __ " \
  "/---/  |" \
  "|  d   |" \
  "--------" \
  "$1"
}


shopt -s nullglob

dirs=(*/)

for d in "${dirs[@]}"; do
  Pdir "$d"
done

Se você fizer quiser processar todos os arquivos, por exemplo, a=(*) e testá-los explicitamente, em vez de usar stat , use um teste direto de shell

[ -d "$i" ]

(execute help test no shell para ver as opções).

    
por steeldriver 10.06.2017 / 14:10

Tags