83 votes

Générer un nom de fichier aléatoire dans le shell unix

Je voudrais générer un nom de fichier aléatoire dans un shell unix (disons tcshell). Le nom de fichier doit être composé de 32 lettres hexadécimales aléatoires, par exemple :

c7fdfc8f409c548a10a0a89a791417c5

(à laquelle j'ajouterai ce qui est nécessaire). Le but est de pouvoir le faire uniquement en shell sans avoir recours à un programme.

132voto

fmark Points 15028

En supposant que vous êtes sur un linux, ce qui suit devrait fonctionner :

cat /dev/urandom | tr -cd 'a-f0-9' | head -c 32

Ce n'est que pseudo-aléatoire si votre système manque d'entropie, mais il est (sous linux) garanti de se terminer. Si vous avez besoin de données véritablement aléatoires, cat /dev/random au lieu de /dev/urandom . Ce changement fera en sorte que votre code se bloque jusqu'à ce que suffisamment d'entropie soit disponible pour produire une sortie vraiment aléatoire, ce qui pourrait ralentir votre code. Pour la plupart des utilisations, la sortie de /dev/urandom est suffisamment aléatoire.

Si vous êtes sous OS X ou un autre BSD, vous devez le modifier comme suit :

cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 32

46voto

Oleg Razgulyaev Points 2140

Pourquoi ne pas utiliser la commande mktemp d'unix :

$ TMPFILE=`mktemp tmp.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` &&  echo $TMPFILE
tmp.MnxEsPDsNUjrzDIiPhnWZKmlAXAO8983

21voto

Dennis Williamson Points 105818

Une commande, pas de tuyau, pas de boucle :

hexdump -n 16 -v -e '/1 "%02X"' -e '/16 "\n"' /dev/urandom

Si vous n'avez pas besoin de la nouvelle ligne, par exemple lorsque vous l'utilisez dans une variable :

hexdump -n 16 -v -e '/1 "%02X"' /dev/urandom

L'utilisation de "16" génère 32 chiffres hexadécimaux.

7voto

Dennis Williamson Points 105818

Comme vous l'avez probablement remarqué dans chacune des réponses, vous avez généralement ont pour "recourir à un programme".

Cependant, sans utiliser tout exécutable externe dans Bash et ksh :

string=''; for i in {0..31}; do string+=$(printf "%x" $(($RANDOM%16)) ); done; echo $string

dans zsh :

string=''; for i in {0..31}; do string+=$(printf "%x" $(($RANDOM%16)) ); dummy=$RANDOM; done; echo $string

Changez les minuscules x dans la chaîne de format à une majuscule X pour que les caractères alphabétiques hexagonaux soient en majuscules.

Voici une autre façon de le faire en Bash, mais sans boucle explicite :

printf -v string '%X' $(printf '%.2s ' $((RANDOM%16))' '{00..31})

Dans ce qui suit, "premier" et "second". printf fait référence à l'ordre dans lequel ils sont exécutés plutôt qu'à l'ordre dans lequel ils apparaissent dans la ligne.

Cette technique utilise l'expansion des accolades pour produire une liste de 32 nombres aléatoires mod 16 suivis chacun d'un espace et d'un des nombres de la plage entre accolades suivi d'un autre espace (par ex. 11 00 ). Pour chaque élément de cette liste, le premier printf supprime tous les caractères sauf les deux premiers en utilisant sa chaîne de format ( %.2 ) en laissant soit des chiffres simples suivis d'un espace chacun, soit deux chiffres. L'espace dans la chaîne de format garantit qu'il y a au moins un espace entre chaque chiffre de sortie.

La substitution de commande contenant la première printf n'est pas cité, de sorte que le découpage des mots est effectué et que chaque nombre va au deuxième. printf comme un argument distinct. Là, les nombres sont convertis en hexadécimal par la fonction %X et ils sont ajoutés les uns aux autres sans espace (puisqu'il n'y en a pas dans la chaîne de format) et le résultat est stocké dans la variable nommée string .

Quand printf reçoit plus d'arguments que sa chaîne de format ne le permet, le format est appliqué à chaque argument tour à tour jusqu'à ce qu'ils soient tous consommés. S'il y a moins d'arguments, la chaîne de format non correspondante (portion) est ignorée, mais cela ne s'applique pas dans ce cas.

Je l'ai testé dans Bash 3.2, 4.4 et 5.0-alpha. Mais il ne fonctionne pas dans zsh (5.2) ou ksh (93u+) car RANDOM n'est évalué qu'une seule fois dans l'expansion de l'accolade dans ces coquilles.

Notez qu'en raison de l'utilisation de l'opérateur mod sur une valeur allant de 0 à 32767, la distribution des chiffres en utilisant les extraits pourrait être faussée (sans parler du fait que les chiffres sont pseudo aléatoire en premier lieu). Cependant, comme nous utilisons le mod 16 et que 32768 est divisible par 16, cela ne posera pas de problème ici.

Dans tous les cas, la manière correcte de procéder est d'utiliser mktemp dans le cas de Oleg Razgulyaev's réponse.

6voto

danran Points 61

uuidgen génère exactement cela, sauf que vous devez enlever les traits d'union. J'ai donc trouvé que c'était la manière la plus élégante (du moins pour moi) d'y parvenir. Il devrait fonctionner sous linux et OS X.

uuidgen | tr -d '-'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X