ubuntu serverでフォルダ内にフォルダがある階層構造になっている。中のフォルダをランダムに抽出したい。サンプルを提示してほしい。なお、抽出したフォルダに対して別途作ったスクリプトを動かす予定。

ubuntu server(Linux)で、特定のディレクトリ配下にある子フォルダをランダムに抽出する方法はいくつかあります。

後続の自作スクリプトにパスを渡しやすいよう、シンプルで堅牢な手法を紹介します。

1. shuf コマンドを使う(最も標準的)

Ubuntuには標準で shuf という行をシャッフルするコマンドが入っています。これと find を組み合わせるのが最も簡単です。

1つだけランダムに抽出してパスを表示する:

bash

find /path/to/target_dir -mindepth 1 -maxdepth 1 -type d | shuf -n 1
  • -mindepth 1 -maxdepth 1: 指定したフォルダの「直下」にあるフォルダのみを対象にします。
  • -type d: ディレクトリ(フォルダ)のみを抽出します。
  • shuf -n 1: シャッフルして上から1行だけ取り出します。

2. 変数に格納してスクリプトを実行する

「抽出したフォルダに対してスクリプトを動かす」という用途であれば、以下のようなワンライナーやシェルスクリプトが実用的です。

ワンライナーの例:

bash

# ランダムに選ばれた1つのフォルダパスを変数 target に入れ、スクリプトを実行
target=$(find /path/to/target_dir -mindepth 1 -maxdepth 1 -type d | shuf -n 1) && ./your_script.sh "$target"

複数(例: 3つ)選んで連続で処理する場合:

bash

find /path/to/target_dir -mindepth 1 -maxdepth 1 -type d | shuf -n 3 | while read dir; do
    echo "Processing: $dir"
    ./your_script.sh "$dir"
done

3. 注意点:フォルダ名にスペースがある場合

フォルダ名にスペースや特殊文字が含まれている可能性がある場合は、-print0 と shuf -z を使うと安全です。

bash

# ヌル文字区切りで処理(最も安全な方法)
target=$(find /path/to/target_dir -mindepth 1 -maxdepth 1 -type d -print0 | shuf -z -n 1 | tr -d '\0')
./your_script.sh "$target"

応用:もっと深く(階層を問わず)探したい場合

もし直下だけでなく、サブフォルダのさらに中にあるフォルダもランダムに抽出したい場合は、-maxdepth 1 を外してください。

bash

find /path/to/target_dir -type d | shuf -n 1

まずは、「対象のフォルダが何個くらいあるか」「一度に何個抽出したいか」を教えていただければ、より最適なコードに調整します。

1度に抽出するのは1フォルダのみ。対象のフォルダは現在500個ぐらいで増える予定。

対象フォルダが500個以上あり、今後も増える予定とのことですので、動作の軽快さと堅牢性を重視したスクリプト例を提示します。

Ubuntu Serverで標準的に利用できる shuf コマンドは、数百〜数千程度の項目数であれば一瞬で処理が完了するため、非常に効率的です。 

推奨される実行コマンド

後続のスクリプトへ確実にパスを渡すため、以下の書き方を推奨します。

bash

# 1. ランダムに1つのフォルダを抽出して変数に格納
# 2. そのフォルダが存在する場合のみ、自作スクリプトを実行
target_dir=$(find /path/to/parent_dir -mindepth 1 -maxdepth 1 -type d | shuf -n 1)

if [ -n "$target_dir" ]; then
    /path/to/your_script.sh "$target_dir"
else
    echo "対象のフォルダが見つかりませんでした。"
fi

ポイント

  • 高速な処理find と shuf の組み合わせは、数千個のフォルダに対しても非常に高速に動作します。
  • 階層の固定-mindepth 1 -maxdepth 1 を指定することで、親フォルダ自身(.)を除外し、直下の子フォルダのみを正確に抽出します。
  • スペース対応: もしフォルダ名にスペースが含まれる可能性がある場合は、以下のように find の -print0 オプションと shuf の -z オプションを組み合わせると安全です。 

bash

# フォルダ名にスペースがある場合でも安全な書き方
target_dir=$(find /path/to/parent_dir -mindepth 1 -maxdepth 1 -type d -print0 | shuf -z -n 1 | tr -d '\0')

この方法であれば、フォルダが数千、数万と増えても Ubuntu Server 上で安定して動作します。

抽出されたフォルダに対して、どのような頻度(cronなど)でスクリプトを実行する予定ですか?設定方法についてサポートが必要であればお知らせください。

一日に1回抽出可能であればOKです。起動時に抽出して以後1日そのフォルダを使います。

「起動時に1回だけランダムにフォルダを選び、その日1日はそのフォルダを使い続ける」という運用ですね。

Ubuntu Serverでこれを実現するには、「起動時にランダム抽出して結果をファイルに保存する」仕組みを作るのが最も確実です。

1. 起動時にフォルダを固定する仕組み

まず、起動時にランダムで1つフォルダを選び、そのパスを /tmp/today_folder.txt などの固定ファイルに書き出す設定をします。

手順 A: 抽出用のスクリプト作成

/usr/local/bin/select_today_folder.sh として保存します。

bash

#!/bin/bash
# 親ディレクトリのパス
PARENT_DIR="/path/to/parent_dir"
# 結果を保存する一時ファイル
SAVE_FILE="/tmp/today_folder.txt"

# ランダムに1つ選んでファイルに保存
find "$PARENT_DIR" -mindepth 1 -maxdepth 1 -type d | shuf -n 1 > "$SAVE_FILE"

# 選ばれたフォルダに対して自作スクリプトを実行
TARGET=$(cat "$SAVE_FILE")
if [ -n "$TARGET" ]; then
    /path/to/your_script.sh "$TARGET"
fi

作成後、実行権限を与えます: sudo chmod +x /usr/local/bin/select_today_folder.sh

手順 B: 起動時に実行させる (crontab)

Ubuntu Serverで最も手軽なのは cron の @reboot 指定です。

  1. crontab -e を実行。
  2. 末尾に以下を追記して保存します。bash@reboot /usr/local/bin/select_today_folder.sh

2. そのフォルダを「1日中」使う方法

他のスクリプトやコマンドから「今日選ばれたフォルダ」を参照したいときは、先ほど書き出したファイルを読み込むだけです。

例:他のシェルスクリプトから使う場合

bash

# 今日選ばれたフォルダのパスを変数に読み込む
TODAY_DIR=$(cat /tmp/today_folder.txt)

echo "本日の対象フォルダは $TODAY_DIR です。"
# 以降、この $TODAY_DIR を使って処理を行う

この方法のメリット

  • 一度決まったら変わらない/tmp 内のファイルに書き出すため、OSを再起動しない限り、その日はずっと同じフォルダを指し示します。
  • 再試行が簡単: もし手動で選び直したい場合は、スクリプトを再度叩くだけで /tmp/today_folder.txt が更新されます。
  • メンテナンス性: フォルダが500個から数千個に増えても、find と shuf は一瞬で処理を終えるため、起動時間を遅延させません。

もし「サーバーを数日間起動しっぱなしにする」可能性がある場合は、@reboot の代わりに毎日決まった時間(深夜0時など)に更新する設定も可能です。必要であれば、その設定方法も提示できます。

いえ大丈夫です。この方法を試してみます。ありがとうございました。

承知いたしました!ぜひその方法で進めてみてください。

もし実際に動かしてみて、特定のフォルダを除外したくなったり、実行結果のログを残したくなったりするなど、追加の要望が出てきましたらいつでもご相談ください。

作業の成功を祈っております!

自作スクリプトの引数渡しパスの指定で詰まった際などは、またいつでもお声がけください。