移动一个文件名中的人物 - Move around the characters in a filename

- 此内容更新于:2015-12-20
主题:

我有一个文件夹的文件名字ab1234,abc5678,等等,我想他们abc3412切换,abc7856,等等?爅科大交换最后两个和倒数第二个字符两个字符。这种格式的文件名都,没有惊喜。有什么简单的方法一个正则表达式?

原文:

I've got a folder full of files with the names ab1234, abc5678, etc., and I want to switch them to abc3412, abc7856, etc. – just swap the last two characters out with the second-to-last two characters. The filenames are all in this format, no surprises. What's the easiest way to do this with a regex?

解决方案:
使用?
原文:

Use perl rename?

rename 's/(..)(..)$/$2$1/' *
解决方案:
根据您的平台,您可能有一个实用程序,可以直接做你想做的事情。例如,anishsane使用基于perl的回答显示了一个优雅的选择重命名工具。这里有一个posix兼容的方法:逐行打印当前文件夹中所有文件(如果有子目录。,你必须排除),包含在双引号。产生2输出线:按原样打印输入行。比赛最后2字符对(在关闭之前)输入线和互换。每个输入线产生的净效应是一对输出线:原文件名,和目标文件名,每个包含在双引号。然后读取双输入(行),并调用实用程序与每一行作为自身的参数,其结果所需的重命名。在每一行包含在双引号可以确保把它们作为一个参数,即使他们应该包含空格。的帽子为enclose-in-literal-double-quotesanishsane方法,使健壮的解决方案。注意:如果你愿意使用posix功能,可以简化命令,如下所示,绕过需要额外的引用:GNUxargs:非标准选项告诉xargs不是对线路进行分词和治疗每一行作为一个参数。BSDxargs(也适用于GNUxargs):替换换行字符(空),然后指定为输入行分隔符字符。xargs的标准选择,再次确保每个输入行作为一个参数。
原文:

Depending on your platform, you may have a rename utility that can directly do what you want. For instance, anishsane's answer shows an elegant option using a Perl-based renaming utility.

Here's a POSIX-compliant way to do it:

printf '"%s"\n' * | sed 'p; s/\(..\)\(..\)"$/\2\1"/' | xargs -L 2 mv
  • printf '"%s"\n' * prints all files in the current folder line by line (if there are subdirs., you'd have to exclude them), enclosed in literal double-quotes.
  • sed 'p; s/\(..\)\(..\)"$/\2\1"/' produces 2 output lines:
    • p prints the input line as-is.
    • s/\(..\)\(..\)"$/\2\1"/' matches the last 2 character pairs (before the closing ") on the input lines and swaps them.
    • The net effect is that each input line produces a pair of output lines: the original filename, and the target filename, each enclosed in double-quotes.
  • xargs -L 2 mv then reads pairs of input lines (-L 2) and invokes the mv utility with each line as its own argument, which results in the desired renaming. Having each line enclosed in double-quotes ensures that xargs treats them as a single argument, even if they should contain whitespace.

Tip of the hat to anishsane for the enclose-in-literal-double-quotes approach, which makes the solution robust.

Note: If you're willing to use non-POSIX features, you can simplify the command as follows, to bypass the need for extra quoting:

  • GNU xargs:

    printf '%s\n' * | sed 'p; s/\(..\)\(..\)$/\2\1/' | xargs -d '\n' -L 2 mv
    

    Nonstandard option -d '\n' tells xargs to not perform word splitting on lines and treat each line as a single argument.

  • BSD xargs (also works with GNU xargs):

    printf '%s\n' * | sed 'p; s/\(..\)\(..\)$/\2\1/' | tr '\n' '\0' | xargs -0 -L 2 mv
    

    tr '\n' '\0' replaces newlines with \0 (NUL) chars, which is then specified as the input-line separator char. for xargs with the nonstandard -0 option, again ensuring that each input line is treated as a single argument.

网友:我建议,照顾文件名与空间(空间中最常见的IFS字符的文件名)。

(原文:I would suggest printf '"%s"\n' * | sed 'p; s/\(..\)\(..\)"$/\2\1"/', to take care of the filenames with spaces (spaces being the most common IFS characters in filenames).)

网友:@anishsane:太好了,谢谢你。我把你的建议到答案,我还添加了posix的替代品,消除需要嵌入式引用。

(原文:@anishsane: Excellent point, thank you. I've incorporated your suggestion into the answer, and I've also added non-POSIX alternatives that obviate the need for embedded quoting.)

网友:在GNUxargs情况下:是什么?项不可用ubuntu,我认为……还是一个错字?

(原文:In GNU xargs case: xargs -d '\n' -L 2 de what is de? That utulity is not available on ubuntu I think... Or is it a typo?)

网友:@anishsane:我的坏:这是一个测试工件;现在应该是——固定。(自定义调试工具的名称代表调试呼应,和,它的目的是显示参数界限。)

(原文:@anishsane: My bad: it was a testing artifact; it was supposed to be mv - fixed now. (de is a custom debug utility whose name stands for debug echo, and whose purpose is to show argument boundaries.))