很多我下载的文件在他们的文件名中有垃圾邮件/垃圾邮件,例如
[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重命名文件.