很多我下载的文件在他们的文件名中有垃圾邮件/垃圾邮件,例如
[www.crap.com] file.name.ext
www.crap.com – file.name.ext
我想出了两种处理方法,但是他们似乎很笨重:
参数扩展:
if [[ ${base_name} != ${base_name//\[+([^\]])\]} ]] then mv -v "${dir_name}/${base_name}" "${dir_name}/${base_name//\[+([^\]])\]}" && base_name="${base_name//\[+([^\]])\]}" fi if [[ ${base_name} != ${base_name//www.*.com - /} ]] then mv -v "${dir_name}/${base_name}" "${dir_name}/${base_name//www.*.com - /}" && base_name="${base_name//www.*.com - /}" fi # more of these type of statements; one for each type of frequently-encountered pattern
然后用echo / sed:
tmp=`echo "${base_name}" | sed -e 's/\[[^][]*\]//g' | sed -e 's/\s-\s//g'` mv "${base_name}" "{tmp}"
我觉得参数扩展是更糟糕的两个,但我喜欢它,因为我可以保留相同的变量分配给文件进行进一步处理后重命名(上述代码用于每个文件的脚本中使用文件下载完成后).
所以无论如何,我希望有一个更好/更干净的方式做上述,比我自己更有知识的人可以告诉我,最好是允许我轻松地将旧/原始变量重新分配到新/重命名的文件.
谢谢
解决方法
两个答案:使用
perl重命名或使用纯
bash
因为有些人不喜欢perl,我写了我的bash唯一版本
介绍
是的,这是重命名命令的典型工作,它是专为以下设计:
man rename | sed -ne '/example/,/^[^ ]/p' For example,to rename all files matching "*.bak" to strip the extension,you might say rename 's/\.bak$//' *.bak To translate uppercase names to lower,you'd use rename 'y/A-Z/a-z/' *
更加面向样品
只需放下所有空格和方括号:
rename 's/[ \[\]]*//g;' *.ext
通过编号从1重命名所有.jpg
rename 's/^.*$/sprintf "IMG_%05d.JPG",++$./e' *.jpg
演示:
touch {a..e}.jpg ls -ltr total 0 -rw-r--r-- 1 user user 0 sep 6 16:35 e.jpg -rw-r--r-- 1 user user 0 sep 6 16:35 d.jpg -rw-r--r-- 1 user user 0 sep 6 16:35 c.jpg -rw-r--r-- 1 user user 0 sep 6 16:35 b.jpg -rw-r--r-- 1 user user 0 sep 6 16:35 a.jpg rename 's/^.*$/sprintf "IMG_%05d.JPG",++$./e' *.jpg ls -ltr total 0 -rw-r--r-- 1 user user 0 sep 6 16:35 IMG_00005.JPG -rw-r--r-- 1 user user 0 sep 6 16:35 IMG_00004.JPG -rw-r--r-- 1 user user 0 sep 6 16:35 IMG_00003.JPG -rw-r--r-- 1 user user 0 sep 6 16:35 IMG_00002.JPG -rw-r--r-- 1 user user 0 sep 6 16:35 IMG_00001.JPG
完整的语法用于匹配SO问题,以安全的方式
使用重命名实用程序有一个强大而安全的方式:
由于这是perl常用工具,我们必须使用perl语法:
rename 'my $o=$_; s/[ \[\]]+/-/g; s/-+/-/g; s/^-//g; s/-\(\..*\|\)$/$1/g; s/(.*[^\d])(|-(\d+))(\.[a-z0-9]{2,6})$/ my $i=$3; $i=0 unless $i; sprintf("%s-%d%s",$1,$i+1,$4) /eg while $o ne $_ && -f $_; ' *
测试规则:
touch '[ www.crap.com ] file.name.ext' 'www.crap.com - file.name.ext' ls -1 [ www.crap.com ] file.name.ext www.crap.com - file.name.ext rename 'my $o=$_; ... ... ...' * ls -1 www.crap.com-file.name-1.ext www.crap.com-file.name.ext touch '[ www.crap.com ] file.name.ext' 'www.crap.com - file.name.ext' ls -1 www.crap.com-file.name-1.ext [ www.crap.com ] file.name.ext www.crap.com - file.name.ext www.crap.com-file.name.ext rename 'my $o=$_; ... ... ...' * ls -1 www.crap.com-file.name-1.ext www.crap.com-file.name-2.ext www.crap.com-file.name-3.ext www.crap.com-file.name.ext
… 等等…
…它是安全的,而你不使用-f标志重命名命令:文件将不会被覆盖,如果出现问题,您将收到一条错误消息.
我更喜欢通过使用专用的实用程序,但这甚至可以通过使用纯bash(也就是没有任何叉子)
没有使用任何其他二进制文件比bash(没有sed,awk,tr或其他):
#!/bin/bash for file;do newname=${file//[ \]\[]/.} while [ "$newname" != "${newname#.}" ] ;do newname=${newname#.} done while [ "$newname" != "${newname//[.-][.-]/.}" ] ;do newname=${newname//[.-][.-]/-};done if [ "$file" != "$newname" ] ;then if [ -f $newname ] ;then ext=${newname##*.} basename=${newname%.$ext} partname=${basename%%-[0-9]} count=${basename#${partname}-} [ "$partname" = "$count" ] && count=0 while printf -v newname "%s-%d.%s" $partname $[++count] $ext && [ -f "$newname" ] ;do :;done fi mv "$file" $newname fi done
要以文件作为参数运行,示例:
/path/to/my/script.sh \[*
>用点替换空格和方括号>只用一个 – 替换.-,– .,– 或..的顺序.>测试文件名是否不同,没有任何关系.>测试一个文件是否存在newname …>分割文件名,计数器和扩展名,用于创建索引的新名称>如果一个文件存在newname,则循环> Finaly重命名文件.