使用sed来批量重命名文件
目的
更改这些文件名:
- F00001-0708 RG-biasliuyda
- F00001-0708-CS-akgdlaul
- F00001-0708-VF-hioulgigl
到这些文件名:
- F0001-0708-RG-biasliuyda
- F0001-0708-CS-akgdlaul
- F0001-0708-VF-hioulgigl
shell代码
去testing:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/'
去表演:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/' | sh
我的问题
我不明白sed代码。 我明白什么是替代命令
$ sed 's/something/mv'
手段。 我有一些正则expression式。 但我不明白这里发生了什么事情:
\(.\).\(.*\)
或在这里:
& \1\2/
前者对我来说就是:“一个单一的字符,后面跟着一个单一的字符,然后是任何单个字符的长度序列” – 但是当然,除此之外还有更多。 就后者而言:
& \1\2/
我不知道。 我真的想了解这个代码。 请帮帮我,伙计们
首先,我应该说最简单的方法是使用预先命名或重命名命令。
在Ubuntu上,OSX(Homebrew软件包rename
,MacPorts软件包p5-file-rename
)或其他带有perl rename(prename)的系统:
rename s/0000/000/ F0000*
或者在使用util-linux-ng重命名的系统上,比如RHEL:
rename 0000 000 F0000*
这比等价的sed命令更容易理解。
但至于理解sed命令,sed手册页是有帮助的。 如果你运行man sed并search&(使用/命令来search),你会发现它是s / foo / bar / replacement中的一个特殊字符。
s/regexp/replacement/ Attempt to match regexp against the pattern space. If success‐ ful, replace that portion matched with replacement. The replacement may contain the special character & to refer to that portion of the pattern space which matched, and the special escapes \1 through \9 to refer to the corresponding matching sub-expressions in the regexp.
因此, \(.\)
匹配第一个字符,可以被\1
引用。 那么.
匹配下一个字符,它总是0.然后, \(.*\)
匹配文件名的其余部分,可以用\2
引用。
replacestring使用&
(原始文件名)和\1\2
除了第二个字符(它是0)之外的每个部分都放在一起。
恕我直言,这是一个相当神秘的方式来做到这一点。 如果由于某种原因,重命名命令不可用,并且您想使用sed来重命名(或者您可能正在做一些过于复杂的重命名操作?),那么在正则expression式中更加明确就会使其更具可读性。 也许是这样的:
ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh
能够看到s / search / replacement中实际发生了什么变化,使得它更具可读性。 如果你不小心运行了两次,它也不会吸引你的文件名。
你已经有了sed的解释,现在你可以使用shell,不需要外部命令
for file in F0000* do echo mv "$file" "${file/#F0000/F000}" # ${file/#F0000/F000} means replace the pattern that starts at beginning of string done
最简单的方法是:
for i in F00001*; do mv "$i" "${i/F00001/F0001}"; done
或者可移植地,
for i in F00001*; do mv "$i" "F0001${i#F00001}"; done
这将用F0001
replace文件名中的F00001
前缀。 信贷mahesh在这里: http : //www.debian-administration.org/articles/150
我写了一个小post,里面有两年前使用sed
进行批量重命名的例子:
http://www.guyrutenberg.com/2009/01/12/batch-renaming-using-sed/
例如:
for i in *; do mv "$i" "`echo $i | sed "s/regex/replace_text/"`"; done
如果正则expression式包含组(例如\(subregex\
),那么您可以在replace文本中使用它们作为\1\
, \2
等。
sed
命令
s/\(.\).\(.*\)/mv & \1\2/
意味着取代:
\(.\).\(.*\)
有:
mv & \1\2
就像一个普通的sed
命令一样。 但是,括号&
和\n
标记会稍微改变它。
searchstring匹配(并记忆为模式1)开始时的单个字符,后跟单个字符,随后是string的其余部分(记为模式2)。
在replacestring中,可以引用这些匹配的模式以将它们用作replace的一部分。 您也可以将整个匹配部分称为&
。
因此, sed
命令正在做的是根据原始文件(对于源)和字符1和3开始创buildmv
命令,从而有效地移除字符2(对于目的地)。 它会给你一系列的格式如下:
mv F00001-0708-RG-biasliuyda F0001-0708-RG-biasliuyda mv abcdef acdef
等等。
反斜杠的意思是,“在匹配模式的时候,坚持在这里匹配的东西。” 稍后,在replace文本方面,可以用“\ 1”(第一个括号内的块),“\ 2”(第二个块)等等将这些记忆的片段返回。
圆括号捕捉特定的string供反向数字使用。
如果你真的在做的是删除第二个字符,不pipe它是什么,你可以这样做:
s/.//2
但是你的命令是build立一个mv
命令并将其pipe道输送到shell执行。
这比你的版本更不可读:
find -type f | sed -n 'h;s/.//4;x;s/^/mv /;G;s/\n/ /g;p' | sh
第四个字符被删除,因为find
将每个文件名前加“./”。
ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000\1|' | bash
这是我会做的:
for file in *.[Jj][Pp][Gg] ;do echo mv -vi \"$file\" `jhead $file| grep Date| cut -b 16-| sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ; done
那么如果这看起来不错,添加| sh
| sh
到底。 所以:
for file in *.[Jj][Pp][Gg] ;do echo mv -vi \"$file\" `jhead $file| grep Date| cut -b 16-| sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ; done | sh