在一个目录中有多个以fgh开头的文件,例如:

fghfilea
fghfileb
fghfilec

我想将它们全部重命名为以前缀jkl开头。是否有一个单独的命令来执行该操作,而不是逐个重命名每个文件?


当前回答

(在我的Mac上)用Ruby做这个要容易得多。下面是两个例子:

# for your fgh example. renames all files from "fgh..." to "jkl..."
files = Dir['fgh*']

files.each do |f|
  f2 = f.gsub('fgh', 'jkl')
  system("mv #{f} #{f2}")
end

# renames all files in directory from "021roman.rb" to "021_roman.rb"
files = Dir['*rb'].select {|f| f =~ /^[0-9]{3}[a-zA-Z]+/}

files.each do |f|
  f1 = f.clone
  f2 = f.insert(3, '_')
  system("mv #{f1} #{f2}")
end

其他回答

在文件列表上运行sed表达式的通用脚本(将sed解决方案与重命名解决方案结合在一起):

#!/bin/sh

e=$1
shift

for f in $*; do
    fNew=$(echo "$f" | sed "$e")
    mv "$f" "$fNew";
done

通过向脚本传递一个sed表达式来调用,然后是任何文件列表,就像rename的一个版本:

script.sh 's/^fgh/jkl/' fgh*

这为我使用regexp工作:

我想要这样重命名文件:

file0001.txt -> 1.txt
ofile0002.txt -> 2.txt 
f_i_l_e0003.txt -> 3.txt

使用[a-z|_]+0*([0-9]+.) regexp,其中([0-9]+.)是用于重命名命令的组子字符串

ls -1 | awk 'match($0, /[a-z|\_]+0*([0-9]+.*)/, arr) { print   arr[0]  " "  arr[1] }'|xargs  -l mv

生产:

mv file0001.txt 1.txt
mv ofile0002.txt 2.txt
mv f_i_l_e0003.txt 3.txt

另一个例子:

file001abc.txt -> abc1.txt
ofile0002abcd.txt -> abcd2.txt 

ls -1 | awk 'match($0, /[a-z|\_]+0*([0-9]+.*)([a-z]+)/, arr) { print   arr[0]  " "  arr[2] arr[1] }'|xargs  -l mv

生产:

  mv file001abc.txt abc1.txt
  mv ofile0002abcd.txt abcd2.txt 

警告,小心点。

这是如何使用sed和mv一起执行重命名:

for f in fgh*; do mv "$f" $(echo "$f" | sed 's/^fgh/jkl/g'); done

根据下面的评论,如果文件名中有空格,则可能需要在返回文件名的子函数周围加上引号,以便将文件移动到:

for f in fgh*; do mv "$f" "$(echo $f | sed 's/^fgh/jkl/g')"; done

安装Perl重命名脚本:

sudo cpan install File::Rename

在Stephan202的回答的评论中提到了两个重命名。 基于Debian的发行版有Perl的重命名。Redhat/rpm发行版的重命名为C。 OS X默认没有安装(至少在10.8中),Windows/Cygwin也没有。

这是find + sed + xargs解决方案的扩展版本。

原来的解是这个和这个。

要求:搜索,修剪,正则表达式,重命名

我想重命名多个文件夹中的多个文件。 一些文件夹应该被删除。 我在cygwin上,不能让perl重命名工作,这是最流行的解决方案所需要的(我假设它很慢,因为它似乎没有修剪选项?)

解决方案

使用find可以有效地获取文件(带有修剪),并提供许多自定义选项。 使用sed替换正则表达式。 使用xargs将结果汇集到最终命令中。

例1:重命名*.js文件,忽略node_modules

这个示例查找文件并对找到的文件和重命名的文件进行回显。出于安全考虑,它目前没有移动任何东西。你需要用mv代替echo。

set -x # stop on error
set -e # verbose mode (echo all commands)

find "." -type f -not \( -path "**/node_modules/**" -prune \) -name "*.js" | 
  sed -nE "s/(.*)\/my(.*)/& \1\/YOUR\2/p" |
  xargs -n 2 echo  # echo first (replace with `mv` later)

上面的脚本转换为:

./x/y/my-abc.js

到这个:

./x/y/YOUR-abc.js

溶液分解

find "." -type f -not \( -path "**/node_modules/**" -prune \) -name "*.js" Searches for files (-type f). The -not part excludes (and, importantly does not traverse!) the (notoriously ginormous) node_modules folder. File name must match "*.js". You can add more include and exclude clauses. Refs: This post discusses recursive file finding alternatives. This post discusses aspects of pruning and excluding. man find sed -nE "s/(.*)\/my\-(.*\.js)/& \1\/YOUR-\2/p" NOTE: sed always takes some getting used to. -E enables "extended" (i.e. more modern) regex syntax. -n is used in combination with the trailing /p flag: -n hides all results, while /p will print only matching results. This way, we only see/move files that need changing, and ignore all others. Replacement regex with sed (and other regex tools) is always of the format: s/regex/replacement/FLAGS In replacement, the & represents the matched input string. This will be the first argument to mv. Refs: linux regex tutorial man sed xargs -n 2 echo Run the command echo with (the first two strings of) the replaced string. Refs: man xargs

好运!