Best way to choose a random file from a directory in a shell script

后端 未结 11 1490
长情又很酷
长情又很酷 2020-12-13 02:00

What is the best way to choose a random file from a directory in a shell script?

Here is my solution in Bash but I would be very interested for a more portable (non-

相关标签:
11条回答
  • 2020-12-13 02:29
    files=(/my/dir/*)
    printf "%s\n" "${files[RANDOM % ${#files[@]}]}"
    

    And don't parse ls. Read http://mywiki.wooledge.org/ParsingLs

    Edit: Good luck finding a non-bash solution that's reliable. Most will break for certain types of filenames, such as filenames with spaces or newlines or dashes (it's pretty much impossible in pure sh). To do it right without bash, you'd need to fully migrate to awk/perl/python/... without piping that output for further processing or such.

    0 讨论(0)
  • 2020-12-13 02:29

    I think Awk is a good tool to get a random number. According to the Advanced Bash Guide, Awk is a good random number replacement for $RANDOM.

    Here's a version of your script that avoids Bash-isms and GNU tools.

    #! /bin/sh
    
    dir='some/directory'
    n_files=`/bin/ls -1 "$dir" | wc -l | cut -f1`
    rand_num=`awk "BEGIN{srand();print int($n_files * rand()) + 1;}"`
    file=`/bin/ls -1 "$dir" | sed -ne "${rand_num}p"`
    path=`cd $dir && echo "$PWD/$file"` # Converts to full path.  
    echo "The randomly-selected file is: $path"
    

    It inherits the problems other answers have mentioned should files contain newlines.

    0 讨论(0)
  • 2020-12-13 02:31
    # ******************************************************************
    # ******************************************************************
    function randomFile {
      tmpFile=$(mktemp)
    
      files=$(find . -type f > $tmpFile)
      total=$(cat "$tmpFile"|wc -l)
      randomNumber=$(($RANDOM%$total))
    
      i=0
      while read line;  do
        if [ "$i" -eq "$randomNumber" ];then
          # Do stuff with file
          amarok $line
          break
        fi
        i=$[$i+1]
      done < $tmpFile
      rm $tmpFile
    }
    
    0 讨论(0)
  • 2020-12-13 02:34

    Something like:

    let x="$RANDOM % ${#file}"
    echo "The randomly-selected file is ${path[$x]}"
    

    $RANDOM in bash is a special variable that returns a random number, then I use modulus division to get a valid index, then reference that index in the array.

    0 讨论(0)
  • 2020-12-13 02:35

    BusyBox (used on embedded devices) is usually configured to support $RANDOM but it doesn't have bash-style arrays or sort --random-sort or shuf. Hence the following:

    #!/bin/sh
    FILES="/usr/bin/*"
    for f in $FILES; do  echo "$RANDOM $f" ; done | sort -n | head -n1 | cut -d' ' -f2-
    

    Note trailing "-" in cut -f2-; this is required to avoid truncating files that contain spaces (or whatever separator you want to use).

    It won't handle filenames with embedded newlines correctly.

    0 讨论(0)
提交回复
热议问题