Ich möchte einen zufälligen Dateinamen in einer Unix-Shell generieren (sagen wir tcshell). Der Dateiname sollte aus zufälligen 32 Hex-Buchstaben bestehen, z.
c7fdfc8f409c548a10a0a89a791417c5
(zu dem ich hinzufügen werde, was notwendig ist). Der Punkt ist, dass es nur in der Shell möglich ist, ohne auf ein Programm zurückzugreifen.
Antworten:
Angenommen, Sie arbeiten unter Linux, sollte Folgendes funktionieren:
cat /dev/urandom | tr -cd 'a-f0-9' | head -c 32
Dies ist nur dann pseudozufällig, wenn Ihrem System die Entropie ausgeht, aber (unter Linux) garantiert beendet wird. Wenn Sie wirklich zufällige Daten benötigen, wählen Sie
/dev/random
statt Katze/dev/urandom
. Durch diese Änderung wird Ihr Code blockiert, bis genügend Entropie verfügbar ist, um eine wirklich zufällige Ausgabe zu erzeugen, sodass Ihr Code möglicherweise verlangsamt wird. Für die meisten Anwendungen ist die Ausgabe von/dev/urandom
ausreichend zufällig.Wenn Sie unter OS X oder einem anderen BSD arbeiten, müssen Sie es wie folgt ändern:
cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 32
quelle
Warum nicht den Unix-Befehl mktemp verwenden?
$ TMPFILE=`mktemp tmp.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` && echo $TMPFILE tmp.MnxEsPDsNUjrzDIiPhnWZKmlAXAO8983
quelle
--dry-run
Flag, um zu verhindern, dass eine Datei erstellt wird. Das eröffnet natürlich eine mögliche Rennbedingung.Ein Befehl, keine Pipe, keine Schleife:
hexdump -n 16 -v -e '/1 "%02X"' -e '/16 "\n"' /dev/urandom
Wenn Sie den Zeilenumbruch nicht benötigen, z. B. wenn Sie ihn in einer Variablen verwenden:
hexdump -n 16 -v -e '/1 "%02X"' /dev/urandom
Bei Verwendung von "16" werden 32 hexadezimale Ziffern generiert.
quelle
hexdump
dafür zu verwenden.Wie Sie wahrscheinlich bei jeder Antwort bemerkt haben , müssen Sie im Allgemeinen "auf ein Programm zurückgreifen".
Ohne externe ausführbare Dateien in Bash und ksh:
string=''; for i in {0..31}; do string+=$(printf "%x" $(($RANDOM%16)) ); done; echo $string
in zsh:
string=''; for i in {0..31}; do string+=$(printf "%x" $(($RANDOM%16)) ); dummy=$RANDOM; done; echo $string
Ändern Sie die Kleinbuchstaben
x
in der Formatzeichenfolge in GroßbuchstabenX
, um die alphabetischen Hex-Zeichen in Großbuchstaben zu setzen.Hier ist eine andere Möglichkeit, dies in Bash zu tun, jedoch ohne explizite Schleife:
printf -v string '%X' $(printf '%.2s ' $((RANDOM%16))' '{00..31})
Im Folgenden
printf
beziehen sich "erste" und "zweite" auf die Reihenfolge, in der sie ausgeführt werden, und nicht auf die Reihenfolge, in der sie in der Zeile erscheinen.Diese Technik verwendet die Klammererweiterung, um eine Liste von 32 Zufallszahlen mod 16 zu erstellen, gefolgt von einem Leerzeichen und einer der Zahlen im Bereich in geschweiften Klammern, gefolgt von einem anderen Leerzeichen (z
11 00
. B. ). Für jedes Element dieser Liste entfernt das ersteprintf
alle bis auf die ersten beiden Zeichen mit seiner Formatzeichenfolge (%.2
), wobei entweder einzelne Ziffern gefolgt von einem Leerzeichen oder zwei Ziffern übrig bleiben. Das Leerzeichen in der Formatzeichenfolge stellt sicher, dass zwischen jeder Ausgabenummer mindestens ein Leerzeichen steht.Die Befehlssubstitution, die die erste enthält,
printf
wird nicht in Anführungszeichen gesetzt, sodass eine Wortaufteilung durchgeführt wird und jede Zahlprintf
als separates Argument an die zweite geht . Dort werden die Zahlen durch die Formatzeichenfolge in hexadezimal%X
konvertiert und ohne Leerzeichen aneinander angehängt (da die Formatzeichenfolge keine enthält). Das Ergebnis wird in der genannten Variablen gespeichertstring
.Wenn
printf
mehr Argumente empfangen werden, als die Formatzeichenfolge berücksichtigt, wird das Format nacheinander auf jedes Argument angewendet, bis alle verbraucht sind. Wenn weniger Argumente vorhanden sind, wird die nicht übereinstimmende Formatzeichenfolge (Teil) ignoriert, dies gilt jedoch in diesem Fall nicht.Ich habe es in Bash 3.2, 4.4 und 5.0-alpha getestet. In zsh (5.2) oder ksh (93u +) funktioniert dies jedoch nicht, da die Klammererweiterung
RANDOM
in diesen Shells nur einmal ausgewertet wird.Beachten Sie, dass aufgrund der Verwendung des Mod-Operators für einen Wert zwischen 0 und 32767 die Verteilung der Ziffern mithilfe der Snippets verzerrt sein kann (ganz zu schweigen von der Tatsache, dass die Zahlen in erster Linie pseudozufällig sind ). Da wir jedoch Mod 16 verwenden und 32768 durch 16 teilbar ist, ist dies hier kein Problem.
In jedem Fall ist der richtige Weg, dies zu tun,
mktemp
wie in der Antwort von Oleg Razgulyaev .quelle
In zsh getestet, sollte mit jeder BASH-kompatiblen Shell funktionieren!
#!/bin/zsh SUM=`md5sum <<EOF $RANDOM EOF` FN=`echo $SUM | awk '// { print $1 }'` echo "Your new filename: $FN"
Beispiel:
quelle
16^32
.md5sum
Binärdatei enthalten. FreeBSD und OSX haben beispielsweise eine,/sbin/md5
die dem gleichen Zweck dient, jedoch unterschiedliche Optionssyntax verwendet.Noch ein anderer Weg [tm].
R=$(echo $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM | md5 | cut -c -8) FILENAME="abcdef-$R"
quelle
Diese Antwort ist fmarks sehr ähnlich, daher kann ich sie nicht wirklich würdigen, aber ich fand die Befehlskombinationen cat und tr ziemlich langsam und fand diese Version ziemlich viel schneller. Du brauchst Hexdump.
hexdump -e '/1 "%02x"' -n32 < /dev/urandom
quelle
-n16
32 Zeichen.Die erste Antwort ist gut, aber warum Gabel Katze, wenn nicht erforderlich.
tr -dc 'a-f0-9' < /dev/urandom | head -c32
quelle
Nimm 16 Bytes von
/dev/random
, konvertiere sie in hexadezimal, nimm die erste Zeile, entferne die Adresse, entferne die Leerzeichen.head /dev/random -c16 | od -tx1 -w16 | head -n1 | cut -d' ' -f2- | tr -d ' '
Angenommen, "ohne auf ein Programm zurückzugreifen" bedeutet natürlich "nur Programme verwenden, die leicht verfügbar sind".
quelle
od
, konnte es aber nicht dazu bringen, das zu tun, was ich wollte. Die Antwort von fmark ist zwar schneller, verarbeitet jedoch möglicherweise schneller.-w16
mit-N16
).Wir hoffen, diesem Thema eine (vielleicht) bessere Lösung hinzufügen zu können.
Hinweis: Dies funktioniert nur mit
bash4
und einigen Implementierungen vonmktemp
(zum Beispiel der GNU).Versuche dies
fn=$(mktemp -u -t 'XXXXXX') echo ${fn/\/tmp\//}
Dieser ist doppelt so schnell wie
head /dev/urandom | tr -cd 'a-f0-9' | head -c 32
und achtmal so schnell wiecat /dev/urandom | tr -cd 'a-f0-9' | head -c 32
.Benchmark:
Mit mktemp:
#!/bin/bash # a.sh for (( i = 0; i < 1000; i++ )) do fn=$(mktemp -u -t 'XXXXXX') echo ${fn/\/tmp\//} > /dev/null done time ./a.sh ./a.sh 0.36s user 1.97s system 99% cpu 2.333 total
Und der andere:
#!/bin/bash # b.sh for (( i = 0; i < 1000; i++ )) do cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 32 > /dev/null done time ./b.sh ./b.sh 0.52s user 20.61s system 113% cpu 18.653 total
quelle
Wenn Sie unter Linux arbeiten, ist Python vorinstalliert. Sie können sich also für etwas Ähnliches wie das Folgende entscheiden:
python -c "import uuid; print str(uuid.uuid1())"
Wenn Ihnen die Bindestriche nicht gefallen, verwenden Sie die Ersetzungsfunktion wie unten gezeigt
python -c "import uuid; print str(uuid.uuid1()).replace('-','')"
quelle
uuidgen
generiert genau dies, außer Sie müssen Bindestriche entfernen. Daher fand ich, dass dies der eleganteste (zumindest für mich) Weg ist, dies zu erreichen. Es sollte unter Linux und OS X sofort funktionieren.uuidgen | tr -d '-'
quelle
Sie können auch den Befehl date wie folgt ausführen:
Liest die Nicht-Sekunden-Zeit und das Ergebnis fügt viel Zufälligkeit hinzu.
quelle
Wenn Sie
openssl
in Ihrem System haben, können Sie es zum Generieren von zufälligen Hex--base64
Strings (auch es kann sein ) mit definierter Länge verwenden. Ich fand es ziemlich einfach und in Cron in One-Line-Jobs verwendbar.quelle