Armazenando uma lista em uma variável

3

Estou tentando armazenar o nome da lista de arquivos que contêm 781 em seu nome. Eu estarei usando esta lista para realizar algumas operações e depois disso eu deletarei esta lista.

Eu tenho duas opções para fazer isso.

Opção 1 : posso armazenar a lista em um arquivo temporário usando o comando abaixo.

ls -lart *781* | awk '{print $9}' > tempo

O arquivo tempo conterá a lista e eu apagarei este arquivo depois de usar.

Opção 2 : Se eu puder de alguma forma armazenar a lista em uma variável e usar essa variável. Eu estou tentando abaixo do código para implementar isso, mas isso não funciona.

filelist='ls -lart *781* | awk '{print $9}''
echo $filelist

Mas o código acima não fornece nenhuma saída. Por favor me ajude com a sintaxe.

Editar : estou usando o k-shell.

    
por g4ur4v 19.12.2012 / 12:53

4 respostas

3

Não use ls para obter a lista de arquivos, especialmente ls * , que fornecerá muitas linhas em branco para diretórios.

Você pode usar (o que nem sempre é bom):

for file in *781*; do
  echo "$file"
done

Que sobreviverá a arquivos com espaços, mas não arquivos com outros caracteres especiais.

Você também pode fazer:

 find . -name "*781*" -print0 | while IFS="" read -r -d "" file; do
   echo "$file"
 done

O que é muito melhor, mas não é padrão em todos os UNIXes (Linux ok).

Em todos os casos, não coloque nomes de arquivos em uma única variável, pois você não pode usar o espaço como um delimitador. Talvez você possa usar matrizes bash como abaixo:

declare -a file_array
while IFS="" read -r -d "" file; do
  file_array[${#file_array[@]}]="$file"
done < <(find . -print0)

Para trabalhar em ksh onde você não tem substituição de processo:

typeset -a file_array
mkfifo mypipe
find . -print0 > mypipe &
while IFS="" read -r -d "" file; do
  file_array[${#file_array[@]}]="$file"
done < mypipe
rm mypipe

Para mais informações, você pode conferir this e isso .

    
por 19.12.2012 / 13:22
0

SUGESTÃO, inspirada na idéia de um canal anônimo, e a necessidade de usar a saída de uma função como entrada para uma matriz, descobri que um co-processo pode ajudar.

MyFunction()
{ echo "One line" ; echo "Second line" ; echo "Third line" }

set -A array
MyFunction 'SomeInputToFunction' < /dev/null |&

while read -p -r line; do
    print "READING from co-process: $line"
    array[ ${#array[@]} ]="$line"
done

Saída:

READING from MyFunction co-process: One line
READING from MyFunction co-process: Second line
READING from MyFunction co-process: Third line

Muito obrigado aos posters anteriores! -Fernando Gonzalez

    
por 31.10.2014 / 09:06
-1

Não tenho certeza de qual shell você está usando, mas com o bash

export filelist='ls -lart *781* | awk '{print $9}''
echo $filelist

como exemplo:

export filelist='ls -l|awk '{print $4}''
echo $filelist
root root sys nobody sys sys sys sys root sys bin root sys root other sys sys root root sys other root sys root sys sys root root
    
por 19.12.2012 / 12:59
-1

Eu não sei porque seus exemplos não estão funcionando. Eles trabalham aqui --- se eu usar uma expressão glob que corresponda a qualquer arquivo. Observe que, se qualquer uma das correspondências puder ser um diretório e você não quiser listar o conteúdo desse diretório, deverá adicionar um -d flag ao seu ls .

Você precisa estar atento ao que acontece quando sua expressão glob não corresponde a nenhum arquivo. O Bash tem uma configuração que você pode ativar com shopt -s failglob , o que gera um erro nesse caso. Em outros shells, ou quando esta opção não foi ativada no bash, você terá a expressão glob como saída. Se você acabou de fazer um echo nonmatching_expression* , verá o resultado "nonmatching_expression *". Se você fizer ls nonmatching_expression* , ls deverá lançar um erro.

Como escrito, ambas as opções assumem que os nomes de arquivos não contêm espaço em branco. Isso é por causa do ls -l ... | awk '{print $9}' . Se você sabe que seus nomes de arquivos não contêm nenhum espaço em branco, tudo bem. (Mas por que você está usando ls -l ... | awk '{print $9}' ao invés de apenas ls ? Eu suponho que você tenha alguma razão que não se manifesta nos exemplos acima.)

Se os seus nomes de arquivos puderem conter novas linhas, as coisas ficarão muito mais difíceis --- não vou entrar no que fazer nesse caso. Se eles não contiverem novas linhas, mas puderem conter outros espaços em branco, você poderá omitir o sinalizador -l em ls e omitir o canal como awk. Então sua primeira opção salvaria no arquivo temporário um nome de arquivo por linha. Esses nomes de arquivos podem conter espaços ou tabulações (mas não novas linhas). Sua segunda opção também armazenaria um nome de arquivo por linha na variável, no entanto, será mais difícil trabalhar com eles.

Se você salvou a lista de nomes de arquivos em uma variável, e os nomes de arquivos podem conter algum espaço em branco, você deve sempre citar a variável ao expandi-la: use echo "$filelist" not echo $filelist .

Veja como eu extrairia os dados:

Opção 1:

while IFS= read -r f; do
  do_stuff_with "$f"
done < tempo

Opção 2:

while IFS= read -r f; do
  do_stuff_with "$f"
done << EOF
$filelist
EOF

Esses métodos permitem que você execute operações dentro do loop (modificando variáveis, alterando diretórios) que estarão visíveis para o restante do script. Se você não se importar com isso, poderá ter a seção while ... done em um pipeline, por exemplo, assim:

echo "$filelist" | while IFS= read -r f; do
  do_stuff_with "$f"
done

Nesse caso, toda a construção while ... done é executada em um subshell e qualquer modificação nas variáveis (incluindo o loop sobre f ) só será visível dentro dessa sub-camada.

Bash e algumas outras shells possuem variáveis de array. Algumas pessoas acham que é mais fácil trabalhar com elas quando os nomes de arquivos podem conter espaços em branco. No entanto, eles são menos portáteis. E eles não podem ser exportados. (Você marcou sua pergunta como /environment-variables , o que, para mim, implica que as variáveis serão exportadas. Mas talvez você não tenha pensado assim.) Não falarei sobre como você pode alcançar seus objetivos com variáveis de matriz. / p>

Se você sabe que não tem nenhum espaço em branco nos seus nomes de arquivos, é mais simples usar sua opção 2 e usar este método:

for f in $filenames; do
    do_stuff_with $f
done

Aqui, as cotações devem ser omitidas em torno de $filenames e são opcionais em torno de $f .

    
por 19.12.2012 / 13:55