特定のディレクトリでファイル名をランダムに指定するには?

特定のディレクトリでファイル名をランダムに指定するには?

さて、奇妙な要求のように聞こえるかもしれませんが、本当に良い目的に役立ちます! JPEG写真のスライドショーを表示できるSDカードスロット付きのパナソニックプラズマテレビがあります。これは画面のやけどを防ぐのに便利です。料理中にしばらくテレビを離れたり、通話中にスライドショーを開始したりすると、静的画像が表示されないようにするのが便利です。そして、写真を見るとずっと別のことをするようになります。

問題は、スライドショーが常にアルファベット順の最初の写真から始まるということです。つまり、常に同じ画像が見えて終わらないことを意味します。私がやりたいことは、私のUnixコンピュータに/media/sdcardSDカード(私がインストールしたもの)で実行できるスクリプトを置き、そのディレクトリにあるすべてのファイルの名前をランダムに指定することです。いいえ本物どのようにランダムに指定するかは関係ありません。しかし、そうします。好む純粋な数字名(明らかな理由なし)

これを達成する簡単な方法はありますか?それはまるでfind /media/sdcard -exec mv {} rand() \;

ボーナスポイントを獲得するためにスクリプトをブロックする方法書く両方のファイルがクラッシュした場合はどうなりますか?写真のコピーだから失うとオリジナルは残るけどそれでも不便そうだな…

答え1

find . -type f |
shuf |  # shuffle the input lines, i.e. apply a random permutation
nl -n rz |  # add line numbers 000001, …
while read -r number name; do
  ext=${name##*/}  # try to retain the file name extension
  case $ext in
    *.*) ext=.${ext##*.};;
    *) ext=;;
  esac
  mv "$name" "../randomized/${name%/*}/$number$ext"
done

適切であると判断された場合、または別のターゲットディレクトリmvに置き換えてください。ランタイムは依然としてディレクトリを巡回する可能性があるため、同じディレクトリ内のファイルの名前を変更したりファイルをリンクしたりしないでください。lnln -sfindmv

shufGNU coreutils のみ、残りは POSIX です。 Linux または Cygwin を使用していない場合は、代替を参照してください。アッまたは真珠

答え2

ここにUnixに関連するものはありません...

import random, os

input_path = "/home/badp/Youtube/" #absolute path for simplicity
output_path = "./playlist"
files = os.listdir(input_path) #assume all files in the same folder for simplicity
random.shuffle(files)

os.mkdir(output_path)
os.chdir(output_path)
i = 0 
for filename in files:
  os.link( os.path.join(input_path, filename),
           str(i) + filename[filename.rfind(os.path.extsep):]
         )         #↑ there must be something cleaner than this :)
  i += 1

フォルダがあると問題が発生しますinput_pathが(ハードリンクできません)、次の助けを借りてファイル「検索」ロジックをより強力なもの(再帰検索など)で簡単に書き換えることができます。os.pathそしてos.walk

答え3

許可された答えと別の良い答えがあります。とにかく、ここに私が使用したスクリプトがあります。フルパスで計算されたハッシュシーケンスに名前を変更して、名前をランダムに指定します。フルパスはシステムごとに一意であるため、ファイル名は競合しません(完全ではなく、確認を追加するのは簡単ですが面倒ではありません)。スクリプトは繰り返しファイル名を変更しますが、ディレクトリ名は変更されていません。再帰的な名前変更を適用するフォルダを引数として渡して使用します。

#! /bin/bash                                                                                                                                             

do_rename() {
    (
    export prevdir="$(pwd)"
    cd "$1"
    for file in *
    do
        if [ -d "$file" ]
        then
            echo "$file is a directory, renaming recursively"
            do_rename "$file"
        elif [ -f "$file" ]
        then
            dirpath="$prevdir/$1"
            oldname="$dirpath/$file"
            name_hash=$(echo "$oldname" | md5sum)
            newname="$dirpath/${name_hash:0:32}.jpg"
            echo "mv $oldname $newname"
            mv $oldname $newname
        fi
    done
    cd "$prevdir"
    )
}

do_rename "$1"

関連情報