$ tree
.
├── foo
│ ├── 1.png
│ └── bar
│ ├── 2.png
│ └── baz
│ └── 3.png
└── script.sh
4 directories, 4 files
$ shopt -s globstar
$ for f in **/*.png; do
base_path="${f%/*}"
[ "${base_path}" = "${f}" ] &&
base_path= ||
base_path="${base_path}/"
mv -n "${f}" "${base_path}${RANDOM}-${RANDOM}-${RANDOM}.png"
done
$ tree
.
├── foo
│ ├── 21462-21532-6024.png
│ └── bar
│ ├── 8568-7432-8514.png
│ └── baz
│ └── 19171-25385-32563.png
└── script.sh
4 directories, 4 files
关于 Zsh 的注释
在 Zsh 中,您无需设置任何 shell 选项即可执行完全相同的操作:
for f in **/*.png; do
base_path="${f%/*}"
[ "${base_path}" = "${f}" ] &&
base_path= ||
base_path="${base_path}/"
mv -n "${f}" "${base_path}${RANDOM}-${RANDOM}-${RANDOM}.png"
done
回答
来自GNU Bash 手册 - Shopt 内置:
所以,以纯粹的 Bash 方式,我会这样做:
${f%/*}
: 将扩展到删除所有内容后剩下的内容,直到从 中/
找到一个字符(包括该/
字符)$f
,从末尾开始(基本上,它将扩展到 的基本路径),或者如果模式没有扩展到$f
的值$f
匹配(例如,如果.png
文件位于当前工作目录中)base_path="${f%/*}"
和前面的部分mv -n "${f}" "${base_path}${RANDOM}-${RANDOM}-${RANDOM}.png"
将设置为空字符串,否则将添加尾随$base_path
$base_path
$f
/
$base_path
-n
mv
:在生成的文件名碰巧匹配的情况下(不太可能),将防止覆盖可能已经存在的文件;在这种情况下,一条消息将打印到屏幕上,您将能够再次旋转该命令关于 Zsh 的注释
在 Zsh 中,您无需设置任何 shell 选项即可执行完全相同的操作:
扩展:使用自定义值代替
$RANDOM
如果您想要的
$RANDOM
数字不是 0-32767 范围内的数字,您可以利用/dev/urandom
生成自定义随机值。例如,要生成长度为 5 的随机字母数字字符串:
tr -dc '[:alnum:]' </dev/urandom
:将从 中不确定地读取/dev/urandom
,仅打印字符集中的字符[:alnum:]
(相当于[0-9A-Za-z]
,因此仅打印数字和大写/小写字母字符)fold -w5
tr
:将分割长度为 5 的行的输出head -n1
:将打印第一行,立即关闭管道请参阅 参考资料 了解
man tr
更多选项。将上面的内容应用到你的命令中(制作
tr -dc '[:alnum:]' </dev/urandom | fold -w5 | head -n1
成一个函数,以避免笨拙地调用它 3 次并设置 3 个$rand_n
变量):扩展:同时处理多个扩展
根据OP的要求:这是一个修改版本,它将同时处理多个扩展(注意:这将仅正确处理诸如 之类的扩展
.bar
,诸如 之类的扩展.foo.bar
将需要更复杂的方法才能正确处理):**/*.{png,gif}
: 将扩展为**/*.png **/*.gif
,最终匹配以 结尾的文件.png
和 以 结尾的文件.gif
${f##*.}
: 将扩展到删除所有内容后剩下的内容,直到从 中.
找到最后一个字符(包括该.
字符)$f
,从头开始(基本上,它将扩展到 的$f
扩展名)您可以使用
find
with-execdir
来避免删除路径组件:(
echo
一旦你很高兴它做了正确的事情,就删除它)。请注意,虽然轻量级 POSIX sh 通常更适合像这样的“scriptlet”,但这里您需要 bash 作为变量RANDOM
。-n
(或等效--no-clobber
)选项可防止在mv
发生名称冲突时覆盖现有文件。如果您不太关心RANDOM是否在 [0,32767] 范围内,那么您可以考虑使用基于 perl 的
rename
命令和String::Random模块(需要 Ubuntu 软件包libstring-random-perl),例如-n
(当您对它做正确的事情感到高兴时删除)。--filename
(或等效地)-d, --nopath, --nofullpath
将操作限制为仅文件名部分:通过此实现
rename
,默认情况下会跳过名称冲突1。这种方法的一个可能的优点是它支持更广泛的随机字符串,例如
要处理多个扩展名,您可以使用正则表达式替换来替换除任意“点后缀”之外的所有内容
或与
File::Basename
模块类似