Como posso randomizar nomes de arquivos em um determinado diretório?

1

Ok, isso pode soar como um pedido estranho, mas realmente tem um bom propósito! Eu tenho uma TV Panasonic Plasma com um slot para cartão SD, através do qual eu posso exibir uma apresentação de slides de fotos JPEG. Isso é útil para evitar o burn-in, se eu me afastar da TV por alguns instantes enquanto estou cozinhando, ou se eu atender o telefone, ou qualquer outra coisa, é fácil começar a apresentação para evitar que uma imagem estática apareça. também deixe-me ver fotos enquanto faço outra coisa.

O problema é que a apresentação de slides sempre começa na primeira foto em ordem alfabética, o que significa que eu sempre vejo as mesmas imagens e nunca chego ao fim. O que eu gostaria de fazer é ter um script na minha máquina Unix que eu possa rodar no cartão SD (montado em /media/sdcard ) e fazer com que os nomes de todos os arquivos sob aquele diretório sejam randomizados. Não realmente importa como isso os randomiza, mas eu prefiro nomes puramente numéricos (sem razão aparente)

Existe uma maneira fácil de conseguir isso? Algo como find /media/sdcard -exec mv {} rand() \; ?

Para pontos de bônus, alguma maneira de impedir que o script substitua dois arquivos no caso de uma colisão? São cópias de fotos, então, se eu perder, ainda tenho o original, mas ainda assim seria inconveniente ...

    
por Josh 27.01.2011 / 21:31

3 respostas

5
find . -type f |
shuf |  # shuffle the input lines, i.e. apply a random permutation
nl -n rz |  # add line numbers 000001, …
while read -r number name; do
  ext=${name##*/}  # try to retain the file name extension
  case $ext in
    *.*) ext=.${ext##*.};;
    *) ext=;;
  esac
  mv "$name" "../randomized/${name%/*}/$number$ext"
done

Substitua mv por ln ou ln -s e possivelmente um diretório de destino diferente como achar melhor. Note que como find ainda pode estar percorrendo o diretório pelo tempo em que mv é executado, você não deve renomear ou vincular o arquivo dentro do mesmo diretório.

shuf é específico do GNU coreutils, o resto é POSIX. Se você não estiver no Linux ou no Cygwin, veja as alternativas em awk ou Perl .

    
por 27.01.2011 / 22:05
2

Não há nada específico para o Unix aqui ...

import random, os

input_path = "/home/badp/Youtube/" #absolute path for simplicity
output_path = "./playlist"
files = os.listdir(input_path) #assume all files in the same folder for simplicity
random.shuffle(files)

os.mkdir(output_path)
os.chdir(output_path)
i = 0 
for filename in files:
  os.link( os.path.join(input_path, filename),
           str(i) + filename[filename.rfind(os.path.extsep):]
         )         #↑ there must be something cleaner than this :)
  i += 1

Isso quebrará se houver pastas em input_path (que você não pode hardlink), mas você pode facilmente reescrever o arquivo "hunting" lógica para algo muito mais robusto (busca recursiva etc.) com a ajuda de os.path e os.walk .

    
por 27.01.2011 / 21:56
0

Eu vejo uma resposta aceita e outra boa resposta. De qualquer forma aqui está um script que eu tenho usado. Ele randomiza os nomes, alterando-os para uma sequência de hash calculada pelo caminho completo. Como o caminho completo é único para cada sistema, é esperado que os nomes dos arquivos não colidam (isso não é à prova de idiotas e adicionar um cheque seria fácil, mas eu não me incomodei). Esse script renomeia os arquivos recursivamente, mas deixa os nomes de diretórios intactos. Use-o passando a pasta para aplicar a renomeação recursiva como um parâmetro.

#! /bin/bash                                                                                                                                             

do_rename() {
    (
    export prevdir="$(pwd)"
    cd "$1"
    for file in *
    do
        if [ -d "$file" ]
        then
            echo "$file is a directory, renaming recursively"
            do_rename "$file"
        elif [ -f "$file" ]
        then
            dirpath="$prevdir/$1"
            oldname="$dirpath/$file"
            name_hash=$(echo "$oldname" | md5sum)
            newname="$dirpath/${name_hash:0:32}.jpg"
            echo "mv $oldname $newname"
            mv $oldname $newname
        fi
    done
    cd "$prevdir"
    )
}

do_rename "$1"
    
por 28.01.2011 / 00:13