Como posso usar um loop dentro de um comando?

1

Estou escrevendo um script de shell que contém um comando que usa vários diretórios como argumentos de entrada separados por espaços (como ls ). Eu gostaria de preencher esses argumentos de uma variável, mas não sei como garantir que palavras como "para" não sejam interpretadas como argumentos. Aqui está um exemplo que expressa minha ideia:

#!/bin/bash

dirs="
 $HOME/Documents
 $HOME/Music
"

ls \
for dir in $dirs
do
    "$dir "
done
    
por Cerran 02.03.2014 / 21:41

1 resposta

4

Em:

dirs="
  $HOME/Documents
  $HOME/Music
"

Você está atribuindo uma string (contendo espaços e caracteres de nova linha e quaisquer que sejam os caracteres $HOME ) a uma variável escalar ( $dirs ).

Em seguida, você deseja passar uma lista de diretórios para ls , ou seja, vários argumentos. Então você precisa de alguma forma dividir essa string em uma lista de argumentos para passar para ls . Como você vai dividir isso? Em espaços e novas linhas? E se $HOME contiver espaços ou novas linhas?

As shells POSIX têm um operador de divisão, na verdade, elas têm um operador split + glob que você invoca deixando uma variável sem aspas. Por sorte, por padrão, a divisão é feita no espaço e na nova linha (e na guia). Então você poderia fazer:

IFS=' ''
' # space and newline
set -f # disable globbing as we want only the
       # splitting part of the split+glob operator
ls -- $dirs

Mas aqui, como queremos uma lista, o melhor seria armazenar os elementos em uma variável do tipo lista, em vez de juntá-los em uma string apenas para dividi-la depois.

Cascas POSIX têm a matriz de parâmetros posicionais ( $1 , $2 ...) para isso:

#! /bin/sh -
set -- ~/Documents ~/Music
ls -- "$@"

Ou se você não se importar em tornar seu script mais lento e menos portátil, use um shell com variáveis de matriz como bash :

#! /bin/bash -
files=(
  ~/Documents
  ~/Music
)
ls -- "${files[@]}"

Ou zsh :

#! /bin/zsh -
files=(
  ~/Documents
  ~/Music
)
ls -- $files
    
por 02.03.2014 / 21:44