5

我已经知道如何在给定目录中执行此操作:

对于*.png中的文件;mv--“$file”“$RANDOM-$RANDOM-$RANDOM.png”完成

如何将其转换为递归命令?

1
  • 2
    仅供参考--$RANDOM-$RANDO-$RANDOM即使你已经意识到$随机的有限范围。详细信息取决于外壳,但随机数生成器的内部状态通常只有32位,这意味着对于$RANDOM-$RANDOM-$RANDOM--而且可能会有比这少得多的序列,和/或一些序列的概率远大于1/2平方米。因此,根据您的需要,您可能会更好地利用/开发/uradom.
    – 鲁阿赫
    评论 5月17日8:49

3个答案

重置为默认值
11

答案

发件人GNU Bash手册-Shopt内置:

全球之星

如果设置,文件名扩展上下文中使用的模式“**”将匹配所有文件以及零个或多个目录和子目录。如果模式后面跟一个“/”,只有目录和子目录匹配。

所以,以纯粹的方式,我会:

shopt-s全球之星对于**/*.png中的f;base_path=“${f%/*}”[“${base_path}”=“${f}”]&&基本路径=||base_path=“${base_path}/”mv-n“${f}”“${base_path}”${随机}-${随机}-${RANDOM}.png“完成
  • ${f%/*}:将扩展到删除所有内容后剩下的内容,直到/找到字符(包括/字符)来自$f美元,从末尾开始(基本上,它将扩展到$f美元的基路径),或设置为的值$f美元如果模式不匹配(例如,在.png码当前工作目录中的文件)
  • 以下章节base_path=“${f%/*}”和之前mv-n“${f}”“${base_path}”${随机}-${随机}-${RANDOM}.png“将设置$基本路径如果的值为$基本路径字符串等于$f美元,或将添加尾部/$基本路径否则
  • -n个:将阻止毫伏在生成的文件名恰好与一个文件名匹配的情况下(不太可能)覆盖可能已经存在的文件;在这种情况下,一条消息将打印到屏幕上,您将能够再次旋转命令
$树.                                                                                                                      ├── foo公司∑-1.png千兆帕∑-2.png⑪——巴兹节气门-3.png└── 脚本.sh4个目录,4个文件$shopt-s全球之星**/*.png中f的$;base_path=“${f%/*}”[“${base_path}”=“${f}”]&&基本路径=||base_path=“${base_path}/”mv-n“${f}”“${base_path}”${随机}-${随机}-${RANDOM}.png“完成$树.├── foo公司2012年-21462-21532-6024.png千兆帕——8568-7432-8514.png千兆赫电话:19171-25385-32563.png└── 脚本.sh4个目录,4个文件

关于Zsh的一点注记

在Zsh中,您可以在不设置任何shell选项的情况下执行完全相同的操作:

对于**/*.png中的f;base_path=“${f%/*}”[“${base_path}”=“${f}”]&&基本路径=||base_path=“${base_path}/”mv-n“${f}”“${base_path}”${随机}-${随机}-${RANDOM}.png“完成

扩展:使用自定义值而不是$随机

如果你愿意$随机要成为0-32767范围内的数字以外的数字,您可以利用/开发/uradom生成自定义随机值。

例如,要生成长度为5的随机字母数字字符串:

tr-dc“[:alnum:]”</dev/urandom|fold-w5|head-n1
  • tr-dc“[:alnum:]”</dev/uradom:将从中不确定地读取/开发/uradom,仅打印字符集中的字符[:铝:](相当于[0-9A-Za-z],因此只打印数字和大小写字母字符)
  • 折叠-w5:将拆分的输出信托收据直线长度为5
  • 头部-n1:将打印第一行,立即关闭管道

请参见手动变速器了解更多选项。

将上述应用于您的命令(使tr-dc“[:alnum:]”</dev/urandom|fold-w5|head-n1到函数中,以避免尴尬地调用它3次并设置3$兰特变量):

函数rand(){tr-dc“[:alnum:]”</dev/urandom|fold-w5|head-n1}shopt-s全球之星对于**/*.png中的f;base_path=“${f%/*}”[“${base_path}”=“${f}”]&&基本路径=||base_path=“${base_path}/”mv-n“${f}”“${base_path}”$(兰德)“-”$(兰特)“-“$(兰德)”.png“完成
$函数rand(){tr-dc“[:alnum:]”</dev/urantom|fold-w5|head-n1}$shopt-s全球之星**/*.png中f的$;base_path=“${f%/*}”[“${base_path}”=“${f}”]&&基本路径=||base_path=“${base_path}/”mv-n“${f}”“${base_path}”$(兰德)“-”$(兰特)“-“$(兰德)”.png“完成$树.├── foo公司-5dL7N-1DHgd-YV6Uw.png型千兆帕2012年-2nwhr-N0YpM-1ABn0.png⑪——巴兹●——IiohU-JTW1k-4PgFk.png└── 脚本.sh4个目录,4个文件

扩展:一次处理多个扩展

根据OP的要求:这是一个修改后的版本,可以同时处理多个扩展(笔记:这只能正确处理扩展,例如.巴,扩展,例如.foo.bar文件将需要一种更复杂的方法来正确处理):

shopt-s全球之星对于**/*中的f。{png,gif};base_path=“${f%/*}”[“${base_path}”=“${f}”]&&基本路径=||base_path=“${base_path}/”ext=“${f#*.}”mv-n“${f}”“${base_path}”${随机}-${随机}-${随机}${ext}“完成
  • **/*.{png,gif}:将扩展到**/*.png**/*.gif,最终匹配以结尾的文件.png码和以结尾的文件.gif文件
  • ${f#*.}:将扩展到删除所有内容后剩下的内容,直到最后.找到字符(包括.字符)来自$f美元,从一开始(基本上,它将扩展到$f美元的扩展名)
$树.├── foo公司∑-1.png千兆帕∑-2.gif千兆赫节气门-3.png└── 脚本.sh4个目录,4个文件$shopt-s全球之星**/*中的f为$。{png,gif};base_path=“${f%/*}”[“${base_path}”=“${f}”]&&基本路径=||base_path=“${base_path}/”ext=“${f#*.}”mv-n“${f}”“${base_path}”${随机}-${随机}-${随机}${ext}“完成$树.├── foo公司——27150-25336-3117.png千兆帕2012年——4841-14490-4418.gif⑪——巴兹电话:-27852-28183-26777.png└── 脚本.sh4个目录,4个文件
5
  • 是否可以将我的其他目标(对.gif、.jpg等也这样做)加入到这个代码中? 评论 5月17日8:39
  • 2
    @努诺·丰塞卡我稍后会扩展第一个例子,请抓紧
    – 科斯
    评论 5月17日11:08
  • 1
    @NunoFonseca我添加了一个版本,可以处理.png码.gif文件文件,您可以更改png、gif在以下条件下对于循环到所需的逗号分隔扩展的任意列表(png、gif、jpg,。。。)它将同时处理所有这些问题
    – kos公司
    评论 5月18日4:22
  • 1
    如果生成的随机名称已经被使用,那么覆盖文件的风险(非常小)。您使用三个单独的随机字符串使得这种情况发生的可能性更小,但您也可以使用类似这样的方法来处理它rname=“${base_path}${随机}-${随机}-${随机}${ext}“;while[[-e”$rname“]];do rname=”${base_path}${随机}-${随机}-${随机}${ext}“;完成
    – 特顿
    评论 5月18日12:07
  • @特登,你完全正确,现在我刚刚补充道-n个并解释说,在这种情况下,人们可能会再旋转一次,使答案“正确”,但是的,它应该自动处理,我想花点时间,明天把整个事情重构得更好(包括您的建议),因为这是一个非常流畅的命令,在处理完所有边缘情况后,它最终结束了,相当臃肿。我想看看还有什么可以做得更好,只需做一个单独的(希望是最终的)编辑。谢谢你提出这个问题
    – kos公司
    评论 5月18日16:04
7

你可以使用找到具有-执行目录为了避免必须剥离路径组件:

找到-名称“*.png”-execdir bash-c对于f;do echo mv-n--“$f”“$RANDOM-$RANDOM-$RANDOM.png”;完成'查找bash{}+

(拆下回声一旦你对自己做的事感到高兴)。注意,虽然像这样的“scriptlet”通常更喜欢使用重量较轻的POSIX-sh,但在这里随机变量。这个-n个(或同等--无电梯)选项阻止毫伏在发生名称冲突时覆盖现有文件。


如果你不特别关心随机在[032767]范围内,则可以考虑使用基于perl的重命名命令,使用字符串::随机模块(需要Ubuntu包libstring-random-perl)例如。

shopt-s全球之星rename-n--文件名-e'开始{使用字符串::Random qw(Random_regex)}$_=随机数(“\\d{5}-\\d日{5}-\\d{5}“).”.png“'--**/*.png

(移除-n个当你高兴它做了正确的事情时)。这个--文件名(或等效-d、 --nopath,--nofullpath)将操作仅限于文件名组件:

-d、 --文件名,--nopath,--nofullpath不重命名目录:仅重命名的文件名组件路径。

通过此实现重命名,默认情况下,跳过名称冲突1.

这种方法的一个可能优点是它支持更广泛的随机字符串,例如

rename-n--文件名-e'开始{use String::Random qw(Random_String)}$_=random_string(“cCncCn”)。“.png”'--**/*.png重命名(foo/1.png,foo/zS3nD1.png)重命名(foo/bar/2.png,foo/bar/kX2gB9.png)重命名(foo/bar/baz/3.png,foo/bar/baz/iU6eB8.png)

要处理多个扩展,可以使用正则表达式替换来替换除任意“点后缀”之外的所有内容,使用展望未来

rename-n--文件名-e'开始{use String::Random qw(Random_String)}s/.*(?=\.[^.]*)/random_string(“cCncCn”)/e' -- **/*.{png,jpg}

或类似于文件::Basename模块

rename-n--文件名-e'开始{使用字符串::Random qw(Random_String);使用文件::Basename qw(fileparse)}$_=random_string(“cCncCn”)。(文件解析($_,qr/\.[^.]*/))[2]' -- **/*.{png,jpg}

[1] 例如给定$ls*.sh美元最佳测试然后$rename的/test/best/“--*.shtest.sh未重命名:best.sh已存在
  • 与另一个答案一样,如果生成的随机名称已经被使用,这也有覆盖文件的风险(非常小)。这是什么--文件名选项?我的perl重命名没有(我在Ubuntu上测试过的也没有)。
    – 特顿
    评论 5月18日12:11
  • 1
    @特顿谢谢-我已将no-clobber选项添加到毫伏版本,但AFAIK基于perl的重命名(尽管不一定是其他类似名称的重命名,例如util-linux命令)始终默认为nolobber。的名称--文件名选项可能是新的,但iirc的几个版本中都有该功能,维护人员似乎无法决定该称之为什么;) 评论 5月18日12:27
  • 1
    @kos谢谢-我错过了这个要求。补充。 评论 5月18日17:45
0

注意:我猜当问题提到“随机化”文件名时,它指的是用随机的不可逆字符串替换原始文件名,并且它没有指定名称必须是#-#-#格式,它只显示了转换的一个示例。

使用对于如果文件名包含空格,则globs可能会失败,因为globbing机制生成一个用空格分隔的单词列表,然后将找到的每个单词逐个分配给对于变量。带有内部空间的名称将产生两个单独的单词。

为了求解递归和空格,我将使用找到,这是递归的,以获得一行中的每个全名,然后将转换应用于每个名称:

#!/垃圾桶/垃圾桶读取文件时查找/pictures-name“*png”|;basedir=“$(dirname”$FILE“)”#获取目录部分filename=“$(basename”$FILE“.png)”#获取名称部分,无扩展名newname=“$(md5sum”$filename“)”#获取dir/filename.png的散列mv“$FILE”“$basedir/${newname}.png”#“移动/重命名”到同一目录完成

如果存在,引号可以避免空格中的单词分裂。还使用了不带路径/扩展名的文件名的md5哈希来最小化同一目录中名称冲突的可能性,而且它不可逆(无法恢复原始名称),就像转换为随机数一样。当然,如果某个名称包含换行符,此方法可能会失败,但在名称中发生这种情况的可能性比在空格中小。

2
  • 您的前提是错误的:文件名扩展发生在分词之后,因此每个文件名都将被视为单个标记,而不管空格是什么(见鬼,它们甚至不会在换行符上拆分):gnu.org/software/bash/manual/html_node/Filename-Expansion.html; 对于文件扩展上的循环不会像您所说的那样失败。OTOH,你的阅读命令将破坏包含前导/尾随空格的文件名,并将拆分包含换行符的文件名(诚然非常边缘情况,但仍然如此)。
    – 科斯
    评论 5月22日6:37
  • 这使得它总体上比使用对于循环+文件名扩展。你的想法是明智的,但它确实需要一些改进(例如:处理文件的惯用方法是找到-name“*png”-print0|而IFS=读取-d$'\0'文件;,这将保留前导/tralinig空格,并且不会在换行符上拆分,而且您应该避免使用所有大写变量,我认为*.png码更安全的搜索模式)
    – 科斯
    评论 5月22日6:37

你必须登录来回答这个问题。

不是你想要的答案吗?浏览标记的其他问题.