Como iterar por meio de uma lista de arquivos com espaços classificados (sem distinção entre maiúsculas e minúsculas)?

6

Eu estou fazendo isso no OSX, que usa o bash, mas obviamente, nem todas as convenções do bash são usadas, então espero que sua sugestão esteja disponível para mim:)

Eu tenho os seguintes arquivos

  1. fun bar1.txt
  2. Foo bar2.tXT (isso é um XT maiúsculo)
  3. fun fun.txt

O que eu era é percorrer a lista de arquivos de forma ordenada?

algo como:

for i in (my-sorted-file-list); do
    echo $i
done

Alguma idéia de como isso pode ser feito? muito obrigado

    
por mrjayviper 23.07.2014 / 06:32

3 respostas

9

Muito simples:

for i in *; do
  echo "<$i>"
done

Isso usa a globalização de arquivos do bash. Uma classificação não é necessária, já que o bash classifica as expansões de nome de caminho.
De man bash :

   Pathname Expansion
       After word splitting, unless the -f option has been set, bash scans each word for
       the characters *, ?, and [. If one of these characters appears, then the word is
       regarded as a pattern, and replaced with an alphabetically sorted list of file
       names matching the pattern.

Exemplo de resultado:

$ touch 'fun bar1.txt' 'Foo bar2.tXT' 'fun fun.txt'

$ for i in *; do echo "<$i>"; done
<Foo bar2.tXT>
<fun bar1.txt>
<fun fun.txt>

Observe que a ordem de classificação depende de LC_COLLATE (assim como o utilitário sort ). Se você quiser uma classificação insensível a maiúsculas e minúsculas, use LC_COLLATE=en_US.utf8 . Se você quiser uma classificação sensível a maiúsculas e minúsculas, use LC_COLLATE=C .

também man bash :

   LC_COLLATE
          This variable determines the collation order used when sorting the results
          of pathname expansion, and determines the behavior of range expressions,
          equivalence classes, and collating sequences within pathname expansion and
          pattern matching.
    
por 23.07.2014 / 07:13
2

Se nenhum contiver novas linhas, você receberá uma lista classificada:

_state=$(set +o)
set -f
IFS='
' ; for f in $(set +f; printf %s\n * |sort) ; do echo "$f" ; done
eval "$_state"

Ou seja, você obterá uma lista ordenada de todos os arquivos no diretório atual - aqui representados por * .

    
por 23.07.2014 / 06:55
2

Uma coisa a ter em mente: em

for i in *.{txt,py,c}; do ...

O *.{txt,py,c} é expandido primeiro para *.txt *.py *.c .

Enquanto *.txt está classificado, *.{txt,py,c} não está. Isso também significa que, se não houver .py file, você percorrerá a string literal *.py .

Se você quiser uma lista global ordenada, você deve usar um operador globbing de alternância em vez de uma expansão de chave. Com bash :

shopt -s extglob
for i in *.@(txt|py|c); do...

Se a classificação será feita com distinção entre maiúsculas e minúsculas é específica do código do idioma. Para forçar a classificação insensível a maiúsculas e minúsculas na localidade atual, com zsh , você pode definir uma nova ordem de classificação como:

ci() REPLY=${(L)REPLY}
for i (*.(txt|py|c))(N.o+ci)) {...}
    
por 23.07.2014 / 14:43