Как я могу перечислить файлы с несколькими критериями в Bash и выбрать случайный? - PullRequest
0 голосов
/ 18 октября 2018

У меня есть каталог файлов такого типа:

1985-08-28_state.txt  2001-04-29_state.txt  2016-12-29_state.txt
1985-08-29_state.txt  2001-04-30_state.txt  2016-12-30_state.txt
1985-08-30_state.txt  2001-05-01_state.txt  2016-12-31_state.txt

И я хочу выбрать все файлы на май-июнь и выбрать случайный из списка.

#!/bin/bash -u

states_path=./daily_states/
date="*-05-*_state.txt *-06-*_state.txt" #Patterns for May-June files
statefile=`ls ${states_path}/$date| shuf -n 1`

printf "$statefile \n"

но это не в состоянии получить доступ ко второму аргументу.

Предупреждение

ls: cannot access *-06-*_state.txt: No such file or directory

Почему это происходит и как я могу это исправить?

Я открыт для любого другого способа сделать это.

Альтернативный ответ

Я подумал о другом способе сделать это.Не самое элегантное решение.Но я думаю, что это работает?

states_path=/daily_states/

statefile[0]=`ls ${states_path}/*-05-*_state.txt | shuf -n 1`
statefile[1]=`ls ${states_path}/*-06-*_state.txt | shuf -n 1`

randstate=$(($RANDOM % 2))

echo "${statefile[$randstate]}"

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

В вашем кратком решении есть несколько проблем:

  • Анализирует вывод ls.Пути с пробелами и т. Д. Могут вызвать проблемы.
  • Распределение выбранных файлов может быть неравномерным.Если первый глобус возвращает 100 файлов, а второй глобус возвращает один файл, вероятность получить этот файл из второго глобуса намного выше, чем получить конкретный файл из первого глобуса.

Здесьальтернатива, которая устраняет эти проблемы и также значительно короче:

 shuf -en1 daily_states/*-05-*_state.txt daily_states/*-06-*_state.txt

Оба глобуса также можно комбинировать следующим образом.

 shuf -en1 daily_states/*-0{5,6}-*_state.txt

Как уже упоминалось, подумайте об использовании shopt -s nullglob -лучше, чем потом сожалеть.

0 голосов
/ 18 октября 2018

Давайте посмотрим, как расширяются ваши переменные.Вы устанавливаете:

date="*-05-*_state.txt *-06-*_state.txt"

И затем вы устанавливаете $statefile с выводом команды:

ls ${states_path}/*-05-*_state.txt *-06-*_state.txt| shuf -n 1

Теперь вы видите проблему?

А лучшеЧтобы справиться с этим, можно использовать массив для хранения шаблонов и другой массив для сбора имен файлов, поскольку синтаксический анализ ls проблематичен :

#!/usr/bin/env bash

states_path=./daily_states/
patterns=("*-05-*_state.txt" "*-06-*_state.txt")

a=()                    # initialize an empty array

shopt -s nullglob       # if no expansion occurs, expand to null

# Step through your patterns...
for monthpat in "${patterns[@]}"; do
  # And add files matching the pattern to the array.
  a+=( $states_path/$monthpat )
done

# Print the list
declare -p a
# or if you prefer,
printf '%s\n' "${a[@]}"

# Or just print one random entry:
printf 'random: %s\n' "${a[ $(( $RANDOM % ${#a[@]} )) ]}"

Обратите внимание, что я не использую shuf, поскольку он не является частью bash и недоступен в операционных системах. Я использую bash (FreeBSD и macOS).


Если вы ЗНАЕТЕ, что вас интересует только эти два месяцафайлы, вы можете выразить их как один глобус.Таким образом:

a=( $states_path/*-0[56]-*_state.txt )
printf '%s\n' "${a[$(($RANDOM%${#a[@]}))]}"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...