Classifique os arquivos em diretórios nomeados pelo prefixo do arquivo

2

Eu tenho um monte de arquivos como este

5830_1.png
5830_2.png
5830_3.png
5831_1.png
5832_1.png
5832_2.png

Gostaria de ordenar todos esses arquivos em diretórios que usam o prefixo do nome do arquivo como o nome do diretório.

Então eu acabaria com

5830/
    5830_1.png
    5831_2.png
    ...etc
5831/
5832/

Existe uma maneira fácil de fazer isso?

    
por Houseman 05.06.2014 / 21:19

2 respostas

8

POSIX sh one-liner:

for file in *.png; do mkdir -p -- "${file%%_*}" && \
    mv -- "$file" "${file%%_*}"; done

Explicação:

  • Faz um loop sobre todos os arquivos .png no diretório atual.
  • mkdir com o prefixo do arquivo; ${file%%_*} remove o primeiro sublinhado e tudo que o segue; o -p garante que mkdir será silencioso se o diretório já existir.
  • mv o arquivo no diretório.

Por sugestão do HalosGhost abaixo, se a estrutura final desejada for

5830/
    1.png
    2.png
    3.png
5831/
    1.png
5832/
    1.png
    2.png

o one-liner acima pode ser modificado levemente:

for file in *.png; do mkdir -p -- "${file%%_*}" && \
    mv -- "${file}" "${file%%_*}/${file##*_}"; done

Desta vez, o destino é composto do diretório ${file%%_*} ( $file before the underscore) e do novo nome de arquivo ${file##*_} ( $file após o sublinhado).

    
por 05.06.2014 / 21:27
1

Eu tive que fazer algo assim para separar alguns arquivos algumas vezes. Eu descobri que a expansão variável do bash é sua amiga.

   ${parameter%word}
   ${parameter%%word}

Remova o padrão de sufixo correspondente. A palavra é expandida para produzir um padrão exatamente como na expansão do nome do caminho.

Configuração inicial:

-rw-r--r-- 1 falsenames falsenames 0 Jun  5 17:35 5830_1.png
-rw-r--r-- 1 falsenames falsenames 0 Jun  5 17:35 5830_2.png
-rw-r--r-- 1 falsenames falsenames 0 Jun  5 17:35 5830_3.png
-rw-r--r-- 1 falsenames falsenames 0 Jun  5 17:35 5831_1.png
-rw-r--r-- 1 falsenames falsenames 0 Jun  5 17:35 5832_1.png
-rw-r--r-- 1 falsenames falsenames 0 Jun  5 17:35 5832_2.png


$ for i in $(find . -maxdepth 1 -type f); do mkdir -p ${i%_*};mv -v $i ${i%_*}; done
'./5830_3.png' -> './5830/5830_3.png'
'./5831_1.png' -> './5831/5831_1.png'
'./5830_1.png' -> './5830/5830_1.png'
'./5832_1.png' -> './5832/5832_1.png'
'./5832_2.png' -> './5832/5832_2.png'
'./5830_2.png' -> './5830/5830_2.png'

Você pode ser mais específico usando '-name * png' ou alguns outros sinalizadores em encontrar também. Eu corri isso através de um achado com maxdepth definido para verificar apenas o diretório especificado. Desta forma, pode ser executado novamente sem modificação, se mais imagens forem adicionadas a esse diretório. Eu também usei% em vez de %% para que isso não quebre se você precisar especificar um diretório completo que inclua um sublinhado, como "/ home / user / my_files / pngs"

$ for i in $(find move_files -maxdepth 1 -type f); do mkdir -p ${i%_*};mv -v $i ${i%_*}; done
'move_files/5830_3.png' -> 'move_files/5830/5830_3.png'
'move_files/5831_1.png' -> 'move_files/5831/5831_1.png'
'move_files/5830_1.png' -> 'move_files/5830/5830_1.png'
'move_files/5832_1.png' -> 'move_files/5832/5832_1.png'
'move_files/5832_2.png' -> 'move_files/5832/5832_2.png'
'move_files/5830_2.png' -> 'move_files/5830/5830_2.png'
    
por 06.06.2014 / 02:54

Tags