Enquanto sua pergunta é marcada com bash
, isso seria um pouco problemático (na minha humilde opinião) usar bash
para tal tarefa. Eu sugeriria usar o python porque ele tem muitas boas funções para tarefas complexas e essa resposta fornece uma solução usando essa linguagem.
Essencialmente, o que ocorre aqui é que usamos o regex para dividir nomes de arquivos em vários delimitadores, obter apenas a primeira parte e usar conjuntos exclusivos dessas primeiras partes como nomes de base para novos diretórios.
Em seguida, percorremos novamente o diretório principal e classificamos os arquivos nos locais apropriados.
O script não faz nada de espetacular, e na análise de algoritmos isso não funcionaria muito bem, por causa dos loops aninhados, mas para a solução "rápida e suja, mas que funciona" está tudo bem. Se você está interessado no que cada linha faz, há muitos comentários adicionados para explicar a funcionalidade
Nota , a demonstração só mostra a impressão dos novos nomes de arquivos apenas para fins de teste. Descomente a parte os.rename()
para mover o arquivo.
A demonstração
bash-4.3$ # Same directory structure as in OP example
bash-4.3$ ls TESTDIR
bash-4.3$ # now run script
AAA AAA.mkv AAA.nfo AAA-picture.jpg BBB BBB-clip.mp4 BBB.mp4 BBB.srt
bash-4.3$ ./collate_files.py ./TESTDIR
/home/xieerqi/TESTDIR/AAA/AAA-picture.jpg
/home/xieerqi/TESTDIR/AAA/AAA.mkv
/home/xieerqi/TESTDIR/AAA/AAA.nfo
/home/xieerqi/TESTDIR/BBB/BBB.srt
/home/xieerqi/TESTDIR/BBB/BBB.mp4
/home/xieerqi/TESTDIR/BBB/BBB-clip.mp4
Script em si
#!/usr/bin/env python
import re,sys,os
top_dir = os.path.realpath(sys.argv[1])
# Create list of items in directory first
# splitting names at multiple separators
dir_list = [os.path.join(top_dir,re.split("[.-]",f)[0])
for f in os.listdir(top_dir)
]
# Creating set ensures we will have unique
# directory namings
dir_set = set(dir_list)
# Make these directories first
for dir in dir_set:
if not os.path.exists(dir):
os.mkdir(dir)
# now get all files only, no directories
files_list = [f for f in os.listdir(top_dir)
if os.path.isfile(os.path.join(top_dir,f))
]
# Traverse lists of directories and files,
# check if a filename starts with directory
# that we're testing now, and if it does - move
# the file to that directory
for dir in dir_set:
id_string = os.path.basename(dir)
for f in files_list:
filename = os.path.basename(f)
if filename.startswith(id_string):
new_path = os.path.join(dir,filename)
print(new_path)
#os.rename(f,new_path)
Notas adicionais:
- O script pode ser adaptado para dividir arquivos em outros separadores múltiplos (na função
re.split()
): adicione entre colchetes (significando"[.-]"
) adicione os caracteres desejados. - A parte móvel é executada com a função
os.rename()
. Alternativamente, você poderiaimport shutil
e usar a funçãoshutil.move()
. Consulte o link