如何随机化给定目录中的文件名?

如何随机化给定目录中的文件名?

好吧,这可能听起来像是一个奇怪的请求,但它确实有一个很好的目的!我有一台带有 SD 卡插槽的松下等离子电视,通过它我可以显示 JPEG 照片的幻灯片。这对于防止烧屏很有用,如果我在做饭时离开电视一会儿,或者如果我接听电话,或者其他什么,只需启动幻灯片即可方便地防止出现静态图像,并且还让我在做其他事情的时候看照片。

问题是幻灯片总是按字母顺序从第一张照片开始,这意味着我总是看到相同的图像并且永远不会结束。我想做的是在我的 Unix 机器上有一个脚本,我可以在 SD 卡(安装在/media/sdcard)上运行该脚本,并让它随机化该目录下所有文件的名称。没有真的不管它如何随机化它们,但我会更喜欢纯数字名称(没有明显原因)

有没有一种简单的方法可以实现这一点?就像是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

替换mvlnln -s,并可能替换为您认为合适的不同目标目录。请注意,由于运行find时可能仍在遍历目录mv,因此您不应重命名或链接同一目录内的文件。

shuf是 GNU coreutils 特有的,其余的是 POSIX。如果您使用的不是 Linux 或 Cygwin,请参阅替代方案awk或者珀尔

答案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.pathos.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"

相关内容