use*_*854 10 unix linux bash shell sed
我下载的很多文件都有文件名中的垃圾/垃圾邮件,例如
[ 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
Run Code Online (Sandbox Code Playgroud)
然后使用echo/sed:
tmp=`echo "${base_name}" | sed -e 's/\[[^][]*\]//g' | sed -e 's/\s-\s//g'`
mv "${base_name}" "{tmp}"
Run Code Online (Sandbox Code Playgroud)
我觉得参数扩展是两者中最差的,但我喜欢它,因为我能够保留分配给文件的相同变量,以便在重命名后进行进一步处理(上面的代码用于为每个文件调用的脚本中文件下载完成后).
所以无论如何我希望有一个更好/更清洁的方式来做上述事情,比我自己更有知识的人可以告诉我,最好是以一种方式让我轻松地将旧/原始变量重新分配给新的/重命名的文件.
谢谢
利用以下经典模式:
job_select /path/to/directory| job_strategy | job_process
Run Code Online (Sandbox Code Playgroud)
where job_select负责选择作业对象,job_strategy为这些对象准备处理计划并job_process最终执行计划.
这假设文件名不包含垂直条|或换行符.
job_select功能
# job_select PATH
# Produce the list of files to process
job_select()
{
find "$1" -name 'www.*.com - *' -o -name '[*] - *'
}
Run Code Online (Sandbox Code Playgroud)
该find命令可以检查文件系统维护的文件的所有属性,如创建时间,访问时间,修改时间.通过告知find不要下载到已安装的文件系统,允许多少递归级别,也可以控制文件系统的探索方式.通常将管道附加到find命令以基于文件名执行更复杂的选择.
避免在job_select函数输出中包含隐藏目录内容的常见缺陷.例如,目录CVS,.svn,.svk并.git使用由相应的源代码控制管理工具,它几乎总是错的,包括在输出的内容job_select的功能.通过无意中批处理这些文件,可以轻松地使受影响的工作副本无法使用.
job_strategy函数
# job_strategy
# Prepare a plan for renaming files
job_strategy()
{
sed -e '
h
s@/www\..*\.com - *@/@
s@/\[^]]* - *@/@
x
G
s/\n/|/
'
}
Run Code Online (Sandbox Code Playgroud)
此命令读取输出job_select并为重命名作业制定计划.该计划由文本行表示,其中两个字段由字符分隔|,第一个字段是文件的旧名称,第二个字段是文件的新计算文件,它看起来像
[ www.crap.com ] file.name.1.ext|file.name.1.ext
www.crap.com - file.name.2.ext|file.name.2.ext
Run Code Online (Sandbox Code Playgroud)
用于制定计划的特定程序基本上是无关紧要的,但通常sed在示例中使用; awk或者perl为此.让我们一起来看看sed这里使用的-script:
h Replace the contents of the hold space with the contents of the pattern space.
… Edit the contents of the pattern space.
x Swap the contents of the pattern and hold spaces.
G Append a newline character followed by the contents of the hold space to the pattern space.
s/\n/|/ Replace the newline character in the pattern space by a vertical bar.
Run Code Online (Sandbox Code Playgroud)
使用多个过滤器来准备计划可能更容易.另一种常见情况是使用该stat命令将创建时间添加到文件名.
job_process函数
# job_process
# Rename files according to a plan
job_process()
{
local oldname
local newname
while IFS='|' read oldname newname; do
mv "$oldname" "$newname"
done
}
Run Code Online (Sandbox Code Playgroud)
所述输入字段分隔符 IFS被调整为让读功能的输出job_strategy.声明oldname和newname本地在大型程序中很有用,但可以在非常简单的脚本中省略.job_process可以调整该功能以避免覆盖现有文件并报告有问题的项目.
关于shell程序中的数据结构
注意使用管道将数据从一个阶段传输到另一个阶段:学徒通常依靠变量来表示这些信息,但事实证明这是一个笨拙的选择.相反,优选的是表示数据作为表格文件或作为移动从一个过程到其它,在这种形式的表格数据流,数据可以很容易地通过有力工具等加工sed,awk,join,paste和sort-只是举最常见的.
由于有些人不喜欢perl,我写了我的 bash only版本
rename命令重命名文件.是的,这是一个典型的rename命令工作,它精确地设计用于:
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/' *
Run Code Online (Sandbox Code Playgroud)
只需删除所有空格和方括号:
rename 's/[ \[\]]*//g;' *.ext
Run Code Online (Sandbox Code Playgroud)
.jpg通过以下编号重命名全部1:
rename 's/^.*$/sprintf "IMG_%05d.JPG",++$./e' *.jpg
Run Code Online (Sandbox Code Playgroud)
演示:
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
Run Code Online (Sandbox Code Playgroud)
使用实用程序有一种强大而安全的方式rename:
由于这是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 $_;
' *
Run Code Online (Sandbox Code Playgroud)
测试规则:
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
Run Code Online (Sandbox Code Playgroud)
... 等等...
...当你不使用-fflag rename命令时它是安全的:文件不会被淹没,如果出现问题你会得到一条错误信息.
我更喜欢使用专用实用程序,但这甚至可以通过使用纯 bash(也就是没有任何分叉)来完成
除了bash(no ,或其他)之外sed,没有使用任何其他二进制文件:awktr
#!/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
Run Code Online (Sandbox Code Playgroud)
要以文件作为参数运行,对于示例:
/path/to/my/script.sh \[*
Run Code Online (Sandbox Code Playgroud)
.-,-.,--或..仅由一个-.| 归档时间: |
|
| 查看次数: |
5408 次 |
| 最近记录: |