问题描述
很多的文件我下载都在其文件名废话/垃圾邮件,例如。
a lot of files I download have crap/spam in their filenames, e.g.
[www.crap.com] file.name.ext
www.crap.com - file.name.ext
我已经想出了两种方式来处理他们,但他们似乎都pretty笨重:
I've come up with two ways for dealing with them but they both seem pretty clunky:
与参数扩展:
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
,然后用回声/ sed的:
and then with echo/sed:
tmp=`echo "${base_name}" | sed -e 's/\[[^][]*\]//g' | sed -e 's/\s-\s//g'`
mv "${base_name}" "{tmp}"
我觉得像参数扩展为两个糟糕,但我喜欢它,因为我能够保持分配给进一步处理文件相同的变量重命名后(以上code是在使用脚本这就是所谓的每个文件的文件下载完成后)。
I feel like the parameter expansion is the worse of the two but I like it because I'm able to keep the same variable assigned to the file for further processing after the rename (the above code is used in a script that's called for each file after the file download is complete).
所以,无论如何,我希望有一个更好/更清洁的方式做到这上面有人更了解比我能告诉我,pferably $ P $的方式,让我很容易老的/原始变量重新分配给新/重命名的文件。
So anyway I was hoping there's a better/cleaner way to do the above that someone more knowledgeable than myself could show me, preferably in a way that would allow me to easily reassign the old/original variable to the new/renamed file.
感谢
推荐答案
由于有一些人不喜欢谁的Perl,我写的我的的bash的唯一版本。
Two answer: using perl rename or using pure bash
As there are some people who dislike perl, I wrote my bash only version
是的,这是一个典型的工作改名
这是precisely设计的命令:
Yes, this is a typical job for rename
command which was precisely designed for:
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
重命名所有 .JPG
从编号 1
:
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
那么匹配问题,以安全的方式完整的语法
有一个强大和安全的方式使用改名
工具:
由于这是常用工具,我们必须使用perl的语法:
As this is perl common tool, we have to use perl syntax:
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
...等等...
... and so on...
......虽然你不使用 -f
标志改名
命令它是安全的:文件韩元'T被overwrited,如果出现错误,你会得到一个错误信息。
... and it's safe while you don't use -f
flag to rename
command: file won't be overwrited and you will get an error message if something goes wrong.
我preFER通过使用专用的工具这样做,但这种甚至可以通过使用纯粹的(又名无任何叉)
I prefer doing this by using dedicated utility, but this could even be done by using pure bash (aka without any fork)
有没有使用任何其他二进制比bash的(没有 SED
, AWK
, TR 或其它):
There is no use of any other binary than bash (no sed
, awk
, tr
or other):
#!/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
要使用文件作为参数来运行,样品:
To be run with files as argument, for sample:
/path/to/my/script.sh \[*
- 更换空间和括号由点
- 更换序列
.-
,-
,-
或..
仅由一个-
- 测试,如果文件名没有什么不同,有什么做的。
- 测试,如果一个文件存在的 NEWNAME ...
- 拆分文件名,计数器和扩展,为使索引的 NEWNAME 的
- 循环,如果一个文件存在的 NEWNAME 的
- Finaly重命名文件。
- Replacing spaces and square bracket by dot
- Replacing sequences of
.-
,-.
,--
or..
by only one-
. - Test if filename don't differ, there is nothing to do.
- Test if a file exist with newname...
- split filename, counter and extension, for making indexed newname
- loop if a file exist with newname
- Finaly rename the file.
这篇关于基于多模式更好的方法来重命名文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!