如何随机化目录文件的选取顺序?含bash实现方案咨询
Hey there! Let's break this down for you. First, I'll show you how to implement the touch-based approach you're thinking of, then share several better alternatives that don't require modifying file metadata (which is usually unnecessary for just picking random files).
touch If you specifically need to randomize file mtimes (e.g., for testing tools that rely on timestamps), here's a bash script that does this safely:
#!/bin/bash # Replace this with your target directory path TARGET_DIR="./your-target-folder" # Loop through all items in the directory for item in "$TARGET_DIR"/*; do # Only process regular files (skip directories, symlinks, etc.) if [ -f "$item" ]; then # Generate a random timestamp between 30 days ago and right now current_timestamp=$(date +%s) thirty_days_ago=$((current_timestamp - 30*24*3600)) random_timestamp=$((thirty_days_ago + RANDOM % (current_timestamp - thirty_days_ago + 1))) # Update the file's modification time touch -d "@$random_timestamp" "$item" echo "Updated mtime for: $item → $(date -d "@$random_timestamp")" fi done
Notes on this script:
- The
RANDOMvariable is bash's built-in random number generator (range 0-32767). For larger time ranges, you can combine multiple calls (e.g.,$((RANDOM + RANDOM*32768))) or useodwith/dev/urandomfor more entropy. - Adjust the
30*24*3600value to change the time range (e.g.,365*24*3600for a full year). - This modifies file metadata, which could interfere with backup tools, sync services, or other processes that rely on mtimes. Use it only if you have a specific need for randomized timestamps.
For your core goal (randomly picking files from a directory), modifying mtimes is a roundabout approach. These methods are simpler, faster, and don't alter any file properties:
Method 1: Use shuf (Simplest & Most Reliable)
shuf is part of the coreutils package (preinstalled on almost all Linux systems). It shuffles input lines, making it perfect for random file selection:
- Pick 1 random file (avoids issues with spaces in filenames):
random_file=$(find "$TARGET_DIR" -maxdepth 1 -type f -print0 | shuf -z -n 1 | xargs -0 echo) echo "Selected file: $random_file" - Pick 3 random files:
Theshuf -n 3 -e "$TARGET_DIR"/* --exclude-dir="*"--exclude-dir="*"flag skips subdirectories.
Method 2: Bash Array (No External Dependencies)
If you're on a system without shuf, use a bash array to store files and pick a random index:
#!/bin/bash TARGET_DIR="./your-target-folder" files=() # Populate array with only regular files for item in "$TARGET_DIR"/*; do [ -f "$item" ] && files+=("$item") done # Handle empty directory case if [ ${#files[@]} -eq 0 ]; then echo "No files found in $TARGET_DIR" exit 1 fi # Select random file random_index=$((RANDOM % ${#files[@]})) echo "Selected file: ${files[$random_index]}"
Method 3: Use sort -R
Another coreutils option: sort -R randomizes input lines, then pipe to head to pick your count:
find "$TARGET_DIR" -maxdepth 1 -type f | sort -R | head -n 1
Unless you specifically need randomized file timestamps, skip the touch-based approach entirely. The direct selection methods are more efficient, safer, and align better with your actual goal of picking random files.
内容的提问来源于stack exchange,提问作者Mike Brown

