使用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 

这将用F0001replace文件名中的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