Como organizar arquivos em diretórios nomeados de acordo com a linha de comando no Linux

1

Eu tenho um diretório preenchido com vários arquivos, com nomes diferentes (ou seja, não nomeados com um padrão específico) e com extensões diferentes, e quero colocar cada arquivo em um subdiretório recém-criado com o nome de cada arquivo; Qual é a melhor maneira de conseguir isso a partir da linha de comando no Linux?
Isso soa um pouco confuso, deixe-me fazer e exemplo: vamos chamar um arquivo aleatório no diretório ./filename.ext , gostaria de colocá-lo em um subdiretório chamado ./filename para que efetivamente o novo caminho seja ./filename/filename.ext .

Eu fiz algumas tentativas com as seguintes etapas:

  • Eu criei alguns arquivos de teste, de file-1.txt a file-9.txt , dentro de um diretório de teste com for num in {1..9}; do touch file-$num.txt; done
  • Eu criei um diretório com o nome de cada nome de arquivo com for name in $(eval ls | cut -b 1-6); do mkdir $name; done
  • Mudei os arquivos de origem em seus respectivos diretórios com for name in $(eval ls | grep -e ".txt" | cut -b 1-6); do mv $name.txt $name/$name.txt; done

Como você pode ver, essa solução funciona, mas sua grande desvantagem é que ela funciona apenas nesse caso, com arquivos desse tamanho de nome de arquivo extact e com essa extensão específica. Se eu tiver alguns arquivos com nomes e extensões diferentes, isso seria inútil. O uso do comando cut não é a solução ideal aqui, suponho, mas não encontrei nada melhor no momento.

Como bônus, seria legal encontrar uma maneira de criar os subdiretórios automaticamente ao mover / renomear os arquivos, sem ter que usar mkdir anteriormente (assim, quando eu ls realmente renomei, não tem que se preocupar em excluir os diretórios recém-criados); mas no final isso é um problema secundário.

    
por Sekhemty 28.09.2013 / 13:09

2 respostas

2

Eu acho que a solução para o seu problema é chamada substituição de parâmetro (dê uma olhada no descrição detalhada ). Dado o nome de um arquivo em filename , você obterá sua extensão usando ${filename##*.} e o nome sem extensão com ${filename%.*} .

Dito isso, você pode querer modificar o seu loop for como:

# for all (*) files in the current directory
for i in *;
do
    # -f checks if it is a file (skip directories)
    [ -f "$i" ] || continue
    # store the file name in filename
    filename=$(basename $i)
    # ext = the extension of the file (here we don't care, jfi)
    ext="${filename##*.}"
    # dir = the file name without its extension
    dir="${filename%.*}"
    # create the directory
    mkdir -p $dir
    # move the file in that directory
    mv $i $dir
done

Infelizmente, eu não entendi o ponto da sua bônus tarefa, então isso continuará sendo um desafio aberto ...:)

    
por 28.09.2013 / 13:32
1

Aqui está uma abordagem com menos scripts de shell, mas mais comandos.

   find -maxdepth 1 -type f > file-list

Encontre todos os arquivos no diretório atual e salve esta lista.

   grep -o '\./.*\.' file-list | sed s/\.$// > dir-list

Filtre esta lista para incluir apenas nomes de arquivos que tenham um ponto em algum lugar. Remova este último ponto com sed, salve esta lista.

   mkdir $(<dir-list)

Crie todas as pastas.

   sort dir-list > dir-list.s
   sort file-list > file-list.s

Isso é para alocar (por ordem listada) os nomes dos arquivos com os nomes das pastas >

   paste file-list dir-list

Isto parecerá incorreto porque o arquivo lista de arquivos estará aqui. No meu caso, também havia um arquivo chamado random . Exclua esses nomes da lista de arquivos.

   sed -E '/^\.\/(random|file-list)$/d' -i file-list
   sort file-list > file-list.s

Investigue a saída do seguinte comando mais uma vez:        cole lista de pastas da lista de arquivos

Deveria ser assim:

   ./CCrtWW].GdH   ./CCrtWW]
   ./c[ifzJlKnEYXO.wXF ./c[ifzJlKnEYXO
   ./FAEhz.u[A ./FAEhz
   ./FGMlrKcJHF.pHp    ./FGMlrKcJHF
   ./HGxKPWZK.MpK  ./HGxKPWZK
   ./JxwNrN.zoj    ./JxwNrN

Uma vez que parece certo, faça um script de shell fora da lista e expire:

 paste file-list dir-list | sed 's/^/mv -v /' | sh
    
por 28.09.2013 / 22:52