Como troco nomes por uma grande quantidade de arquivos em uma pasta?

3

Eu quero randomizar os nomes para cerca de 350 arquivos em uma pasta, mas eu quero ter todos os nomes que os arquivos tinham originalmente. O que quero dizer é que eu quero todos os nomes na minha pasta randomizados a partir dos nomes originais e sem novos nomes e sem nomes perdidos. Isso é possível?

(sinta-se à vontade para editar esta pergunta se eu não tiver dito claramente a minha pergunta)

    
por John Hickox 08.09.2015 / 22:43

5 respostas

1

mkdir aux
ls | shuf > a                                # a=randomize list of files
(tail -n +2 a ; head -1 a) > b               # b=rotate a one line
paste a b > c                                # c=(name1 name2)*
gawk '{system( "mv " $1 " aux/" $2)}' c      # mv name1 -> aux/name2
mv aux/* .                                   # mv aux/name -> name
rm a b                                     

mantenha c para reverter, se necessário. (Escolha um nome melhor para os arquivos auxiliares)

    
por 09.09.2015 / 00:12
0
└-(>:) for i in 'seq -w 1 10'; do echo $i > nonce-$i; done 
└-(>:) ls
nonce-01  nonce-02  nonce-03  nonce-04  nonce-05  nonce-06  nonce-07  nonce-08  nonce-09  nonce-10
└-(>:) for i in nonce*; do echo $i; cat $i; done
nonce-01
01
nonce-02
02
nonce-03
03
nonce-04
04
nonce-05
05
nonce-06
06
nonce-07
07
nonce-08
08
nonce-09
09
nonce-10
10
└-(>:) ../shuffle test
└-(>:) for i in nonce*; do echo $i; cat $i; done
nonce-01
06
nonce-02
03
nonce-03
04
nonce-04
02
nonce-05
09
nonce-06
10
nonce-07
05
nonce-08
08
nonce-09
07
nonce-10
01

E aqui está o código:

#!/bin/bash
[ -z $1 ] && echo 'please submit a target directory' && exit 1 
TargetDir=${1}
cd $TargetDir
Sourcearray=( * )
function checkArray
{
 for item in ${dest[@]}
  do
   [[ "$item" == "$1" ]] && return 0 # Exists in dest
 done
 return 1 # Not found
}
#let's shuffle the array randomly 

while [ "${#dest[@]}" -ne "${#Sourcearray[@]}" ]
do
     rand=$[ $RANDOM % ${#Sourcearray[@]} ] 
      checkArray "${Sourcearray[$rand]}" || dest=(${dest[@]} "${Sourcearray[$rand]}")
done

let i=0 
#let mv the source file to dest file name 
while [[ "${i}" -ne "${#dest[@]}" ]] ; do 
    mv ${Sourcearray[$i]} tmp-${dest[$i]}
    let i=$i+1
done  
# and rename to go back to the original name 
rename 's/tmp-//' *
    
por 08.09.2015 / 23:42
0

Aqui está uma ideia:

  • Obtenha uma lista dos nomes originais. Salve isso.
  • Salve uma versão embaralhada da lista ( sort -R ).
  • Manuseie a lista original de forma não colidindo, por exemplo, acrescentando algo a cada nome.
  • Mova os arquivos originais para que eles reflitam o desfigurado lista (em ordem).
  • Mova os arquivos desconfigurados para que eles reflitam o embaralhado lista original.

No código básico do shell, assumindo que não há novas linhas em nomes de arquivos, o diretório atual é o alvo para embaralhar e o diretório externo pode ser escrito:

  find . -type f > ../list 
  < list sort -R > ../shuffled
  while read f; do mv "$f" "$f".tmp; done < ../list
  exec 3<../shuffled
  while read f; do read s <&3; mv "$f".tmp "$s"; done < ../list
  exec 3>&-  
    
por 08.09.2015 / 23:35
0

Existem, eu sei, maneiras muito mais elegantes de resolver este problema. Esta oferta não funcionará para nomes de arquivos contendo novas linhas ou aqueles que começam com um ponto, mas devem ser razoavelmente robustos de outra forma:

# Create a temporary directory for rename targets (allows for a->b but b->a)
DIR='.tmp'
mkdir -p "$DIR"

# How many files
LS=($(ls))
NLS=$((${#LS}+1))

# Rename the files pseudo-randomly
for SRC in "${LS[@]}"
do
    while :
    do
        # A poor approximation to a random selection. If you have 'shuf'
        # this could be considerably simplified.
        RND=$((RANDOM % NLS))
        DST="${LS[$RND]}"
        echo "(trying RND=$RND -> DST=$DST)" >&2

        # Keep retrying until we find an unused filename
        test -n "$DST" && break
    done
    echo "$SRC -> $DST" >&2
    mv -f "$SRC" "$DIR/$DST"
    unset LS[$RND]
done

# Restore the renamed files to the now-empty directory
mv "$DIR"/* .
rmdir "$DIR"

Se você precisar manipular nomes de arquivos que começam com um ponto, mova o diretório temporário $DIR em outro lugar e modifique o comando ls para incluir o sinalizador -A . Se você precisar manipular nomes de arquivos contendo novas linhas, recomendo que você use uma linguagem diferente, por exemplo, Perl ou Python.

    
por 09.09.2015 / 00:14
-1

Não existe um comando bem conhecido para isso, mas, felizmente, os interpretadores de shell podem fazer isso e tarefas semelhantes com muita facilidade. Por exemplo:

for i in /my/this/dir/*;do mv -vf "$i" "$i.$RANDOM";done

percorrerá os arquivos no diretório /my/this/dir e executará um comando mv (rename) para isso, que acrescenta o nome deles com um número aleatório entre 0 e 32767. Por exemplo, se você executar isso para o /sbin directory, ele irá renomear os arquivos aqui assim:

ifconfig -> ifconfig.4553
ip -> ip.12767
...

NÃO FAÇA ISSO EM / sbin, ELE MATARÁ SEU SISTEMA! (Mas seria muito engraçado :-))

Mas cuidado, se não é o que você quer, pode ser mais difícil (outra linha única, hehe) fazer isso de volta. Portanto, antes de executar esse script, você pode testá-lo com o prefixo mv com echo :

for i in /my/this/dir/*;do echo mv -vf "$i" "$i.$RANDOM";done

Este segundo script oneline não fará nada, apenas imprimirá os comandos mv que ele executaria sem o echo .

    
por 08.09.2015 / 23:06