好吧,这可能听起来像是一个奇怪的请求,但它确实有一个很好的目的!我有一台带有 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
替换mv
为ln
或ln -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.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"