Aqui está um pequeno folheto que fará o que você quer:
$ mkdir -p output/{A..Z}; for i in tstdir/*; do export FILE=$(basename "$i"); LTR=$(echo" ${FILE:0:1}" | tr [a-z] [A-Z]); mv "$i" "output/$LTR/$FILE" ; done
Aqui está o mesmo comando na forma expandida para que você possa ver o que está acontecendo:
$ mkdir -p output/{A..Z}
$ for i in tstdir/*; do
FILE=$(basename "$i")
LTR=$(echo "${FILE:0:1}" | tr [a-z] [A-Z])
mv "$i" "output/$LTR/$FILE"
done
Detalhes
O primeiro acima assume que o diretório de saída de apenas as letras não existe e, portanto, irá criá-lo,
$ mkdir -p output/{A..Z}
O loop for
funciona da seguinte maneira, percorrendo todos os arquivos em tstdir/*
. Em seguida, ele determina o basename
desse caminho e o armazena na variável $FILE
. Cada iteração através do loop é armazenada na variável $i
.
FILE=$(basename "$i")
Em seguida, usamos a capacidade do Bashes para retornar o primeiro caractere da variável nomeada, $FILE
, e depois usar tr
para converter qualquer caractere minúsculo em superior.
LTR=$(echo "${FILE:0:1}" | tr [a-z] [A-Z])
Quebrando isso um pouco mais:
$ echo "${FILE:0:1}"
s
$ echo "${FILE:0:1}"
T
Com o código tr
, agora você pode ver o que está acontecendo:
$ echo "${FILE:0:1}" | tr [a-z] [A-Z]
S
$ echo "${FILE:0:1}" | tr [a-z] [A-Z]
T
O restante do comando apenas move os arquivos para o diretório de primeira letra correspondente.
Exemplo
Digamos que tenhamos este diretório de arquivos:
$ touch {a-z}file {A-Z}file
$ tree tstdir/ | head -10
tstdir/
|-- afile
|-- Afile
|-- bfile
|-- Bfile
|-- cfile
|-- Cfile
|-- dfile
|-- Dfile
|-- efile
...
Depois de executar o um forro:
$ tree output/ | head -10
output/
|-- A
| |-- afile
| '-- Afile
|-- B
| |-- bfile
| '-- Bfile
|-- C
| |-- cfile
| '-- Cfile
...