Генерация случайной строки zsh

Я пытаюсь сгенерировать случайную строку со следующим кодом:

for pic in `ls *.jpg`; do
  rdn=`echo $RANDOM | sha256sum | cut -d" " -f1`
  mv "$pic" ${rnd}.jpg
done

Эта часть скрипта запускается из каталога, содержащего множество файлов JPEG, и она должна рандомизировать их имена файлов. Проблема в том, что $RANDOM переменная не обновляется во время итерации, поэтому каждый раз выдает один и тот же хэш. Я пытался использовать /dev/urandomи это работает, но намного медленнее, чем $RANDOM, Что я могу сделать, чтобы "восстановить" $RANDOM каждый раз это читается?

3 ответа

Решение
for pic in *.jpg; do # Iterate over the jpgs in the current directory.
  dd if=/dev/urandom count=1 2>/dev/null | sha256sum | ( # Gather 512 bytes from /dev/urandom
    read rnd _ # Read the first "word" in the sha256sum output
    mv "$pic" ${rnd}.jpg # rename the jpg.
  )
done

Трубопровод к read вызывает неявную подоболочку, поэтому я создаю явную подоболочку, чтобы гарантировать доступ к rnd параметр. Кроме того, не разбирайте ls

Кстати, вы уверены, что не хотите просто base64 выход? Это намного дешевле, чем sha256sum, и я не вижу, что вы получаете от sha256sum. Кроме того, это облегчит чтение кода:

for pic in *.jpg; do
  mv "$pic" "$(base64 </dev/urandom | tr -dc 'a-zA-Z0-9' | head -c20).jpg"
done

На моем Mac (с использованием MacOS High Sierra) /dev/urandom дает мне двоичные байты, поэтому приведенное выше решение приводит к tr: Illegal byte sequenceтак я использовал base64 преобразовать байты в символы:

cat /dev/urandom | base64 | tr -dc '0-9a-zA-Z' | head -c100

или я нашел решение без base64, чтобы вы могли также получить знаки препинания:

cat /dev/urandom | LC_ALL=C tr -dc '\''[:alnum:]\!\@\#$\-\.\,'\'' | head -c40

Вы можете сделать это более просто, используя cat, tr и head. Например:

cat /dev/urandom | tr -dc '0-9a-zA-Z' | head -c100

tr Команда в этом конвейере удалит любой символ из стандартного ввода, который не соответствует указанному набору символов. head напечатает первые 100 символов и затем выйдет, завершив общую команду.

Это сгенерирует 100-символьную строку, содержащую буквенно-цифровые символы. Чтобы сделать это в переименовании, вам просто нужно использовать подстановку команд:

for file in *.jpg
    mv -n ${file} $(cat /dev/urandom | tr -dc '0-9a-zA-Z' | head -c100).jpg

В зш а for цикл с одним утверждением не должен быть окружен do или же done, -n flag to mv предотвратит перезапись существующего файла - на тот случай, если вам действительно не повезет со случайными строками.

Другие вопросы по тегам