ディレクトリ内のファイルをランダムに繰り返す

ディレクトリ内のファイルをランダムに繰り返す

現在のディレクトリ内のすべてのファイルをランダムに移動するようにどのfor track in *.mp3; doように変更できますか?.mp3

答え1

参考までに、zshglobbing修飾子を使用してglobが拡張される順序に影響を与えることができますo。たとえば、*.mp3(om)修正時間に基づいてソートします。関数を使用して独自のソート順序を定義できます。

を使用すると、ファイルはファイル名に基づいているのではなく、ファイル名が指定された変数(ファイル名も受け取ります)から関数によって返された値*.mp3(o+foo)foo基づいてソートされます。たとえば、$REPLYfoo$REPLY

rand() REPLY=$RANDOM

for i in *.mp3(o+rand); do
  echo "$i"
done

ランダムに注文を受け取ります。

POSIXly、ファイル名に含めることができる内容について何も仮定しない場合は、次のようにします。

shuffle() {
  awk -v q="'" 'BEGIN {
    printf "set --"
    for (i=1; i < ARGC; i++) {
      r=int(rand()*(ARGC-1)+1);x=ARGV[i];ARGV[i]=ARGV[r];ARGV[r]=x
    }
    for (i=1;i<ARGC;i++) {
      a=ARGV[i];gsub(q, q "\\" q q, a);printf " %s", q a q
    }
    print "";exit}' "$@"
}
eval "$(shuffle *.mp3)"
for i do
  echo "$i"
done

答え2

このshufコマンドを使用して行の順序を混在させることができます。 *.mp3 を含むリストコマンドをバックティックに処理してパイプするだけですshuf。たとえば、次のようになります。

#!/bin/bash -
SAVEIFS=$IFS
IFS=$'\n'; set -f
for i in `find . -maxdepth 1 -iname '*.mp3' -type f | shuf`
do
    echo "$i"
done
IFS=$SAVEIFS; set +f

上記はGNUを想定しておりfind、ファイル名に改行文字が含まれていません。

答え3

find . -name \*.mp3 -maxdepth 1 -print0 | shuf -z | while IFS= read -d '' -r l; do printf %s\\n "$l"; done

  • -maxlength、-print0、shuf、およびread -dはPOSIXでは定義されていません。 shufはcoreutilsの一部です。
  • read は、行の先頭と末尾から IFS の文字を削除します。 -r はバックスラッシュ解析を無効にします。-d ''同じです-d $'\0'

または、パスに改行やバックスラッシュが含まれておらず、IFSの文字で始まるか終わらない場合:

printf %s\\n *.mp3 | shuf | while read l; do printf %s\\n "$l"; done

関連情報