目录中有多个文件以前缀fgh
开头,例如:
fghfilea
fghfileb
fghfilec
我想将所有这些重命名为前缀jkl
。是否有单个命令来执行此操作而不是单独重命名每个文件?
答案 0 :(得分:258)
有几种方法,但使用rename
可能是最简单的方法。
使用rename
的一个版本:
rename 's/^fgh/jkl/' fgh*
使用其他版本的rename
(与Judy2K's answer相同):
rename fgh jkl fgh*
您应该查看平台的手册页,了解上述哪一项适用。
答案 1 :(得分:103)
这是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
答案 2 :(得分:69)
重命名可能不在每个系统中。所以如果你没有它,请使用shell bash shell中的这个例子
for f in fgh*; do mv "$f" "${f/fgh/xxx}";done
答案 3 :(得分:36)
使用mmv:
mmv "fgh*" "jkl#1"
答案 4 :(得分:19)
有很多方法可以做到(并非所有这些方法都适用于所有unixy系统):
ls | cut -c4- | xargs -I§ mv fgh§ jkl§
§可能被您认为方便的任何东西取代。您也可以使用find -exec
执行此操作,但在许多系统上行为略有不同,所以我通常会避免这种情况
for f in fgh*; do mv "$f" "${f/fgh/jkl}";done
原油但有效,如他们所说
rename 's/^fgh/jkl/' fgh*
非常漂亮,但BSD上没有重命名,BSD是最常见的unix系统。
rename fgh jkl fgh*
ls | perl -ne 'chomp; next unless -e; $o = $_; s/fgh/jkl/; next if -e; rename $o, $_';
如果您坚持使用Perl,但系统上没有重命名,则可以使用此怪物。
其中一些有点复杂,而且列表还远未完成,但您可以在这里找到几乎所有unix系统的内容。
答案 5 :(得分:13)
rename fgh jkl fgh*
答案 6 :(得分:8)
使用find
,xargs
和sed
:
find . -name "fgh*" -type f -print0 | xargs -0 -I {} sh -c 'mv "{}" "$(dirname "{}")/`echo $(basename "{}") | sed 's/^fgh/jkl/g'`"'
它比@nik's solution更复杂,但它允许递归重命名文件。例如,结构,
.
├── fghdir
│ ├── fdhfilea
│ └── fghfilea
├── fghfile\ e
├── fghfilea
├── fghfileb
├── fghfilec
└── other
├── fghfile\ e
├── fghfilea
├── fghfileb
└── fghfilec
将转变为此,
.
├── fghdir
│ ├── fdhfilea
│ └── jklfilea
├── jklfile\ e
├── jklfilea
├── jklfileb
├── jklfilec
└── other
├── jklfile\ e
├── jklfilea
├── jklfileb
└── jklfilec
使其与xargs
一起使用的关键是invoke the shell from xargs。
答案 7 :(得分:3)
安装Perl rename脚本:
sudo cpan install File::Rename
Stephan202的答案中的评论中提到了two renames。 基于Debian的发行版有Perl rename。 Redhat / rpm发行版有C rename 默认情况下OS X没有安装(至少在10.8中),Windows / Cygwin也没有。
答案 8 :(得分:2)
这是使用命令行Groovy执行此操作的方法:
groovy -e 'new File(".").eachFileMatch(~/fgh.*/) {it.renameTo(it.name.replaceFirst("fgh", "jkl"))}'
答案 9 :(得分:2)
在Solaris上,您可以尝试:
for file in `find ./ -name "*TextForRename*"`; do
mv -f "$file" "${file/TextForRename/NewText}"
done
答案 10 :(得分:2)
#!/bin/sh
#replace all files ended witn .f77 to .f90 in a directory
for filename in *.f77
do
#echo $filename
#b= echo $filename | cut -d. -f1
#echo $b
mv "${filename}" "${filename%.f77}.f90"
done
答案 11 :(得分:1)
在Ruby中执行此操作要容易得多(在我的Mac上)。以下是两个例子:
# 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
答案 12 :(得分:1)
此脚本为我进行了递归重命名,其中目录/文件名可能包含空格:
find . -type f -name "*\;*" | while read fname; do
dirname=`dirname "$fname"`
filename=`basename "$fname"`
newname=`echo "$filename" | sed -e "s/;/ /g"`
mv "${dirname}/$filename" "${dirname}/$newname"
done
请注意sed
表达式,在此示例中,该表达式用空格;
替换了所有的出现。当然,应根据特定需要替换它。
答案 13 :(得分:1)
我的重命名海量文件版本:
for i in *; do
echo "mv $i $i"
done |
sed -e "s#from_pattern#to_pattern#g” > result1.sh
sh result1.sh
答案 14 :(得分:1)
使用StringSolver工具(windows& Linux bash)按示例处理:
filter fghfilea ok fghreport ok notfghfile notok; mv --all --filter fghfilea jklfilea
首先根据示例计算过滤器,其中输入是文件名和输出(ok和notok,任意字符串)。如果filter具有选项--auto或在此命令后单独调用,它将创建文件夹ok
和文件夹notok
并分别将文件推送到它们。
然后使用过滤器, mv
命令是半自动移动,使用修改器--auto自动移动。使用前面的过滤器,感谢--filter,它会找到从fghfilea
到jklfilea
的映射,然后将其应用于所有过滤的文件。
其他单行解决方案
其他相同的方法(每行相同),所以你可以选择自己喜欢的方式。
filter fghfilea ok fghreport ok notfghfile notok; mv --filter fghfilea jklfilea; mv
filter fghfilea ok fghreport ok notfghfile notok; auto --all --filter fghfilea "mv fghfilea jklfilea"
# Even better, automatically infers the file name
filter fghfilea ok fghreport ok notfghfile notok; auto --all --filter "mv fghfilea jklfilea"
多步骤解决方案
要仔细查找命令是否运行良好,您可以键入以下内容:
filter fghfilea ok
filter fghfileb ok
filter fghfileb notok
当您确信过滤器是好的时,请执行第一步:
mv fghfilea jklfilea
如果要测试并使用上一个过滤器,请键入:
mv --test --filter
如果转换不符合您的要求(例如即使使用mv --explain
,您也会发现错误),您可以键入mv --clear
重新启动移动文件,或添加更多示例mv input1 input2
其中input1和input2是其他示例
如果您有信心,只需输入
即可mv --filter
和瞧!所有重命名都是使用过滤器完成的。
免责声明:我是为学术目的而做的这项工作的合着者。很快就会有一个bash产生功能。答案 15 :(得分:1)
我建议使用我自己的脚本来解决这个问题。它还可以选择更改文件名的编码,并将变音符号组合转换为预组合字符,这是我从Mac复制文件时遇到的一个问题。
#!/usr/bin/perl
# Copyright (c) 2014 André von Kugland
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
$help_msg =
"rename.pl, a script to rename files in batches, using Perl
expressions to transform their names.
Usage:
rename.pl [options] FILE1 [FILE2 ...]
Where options can be:
-v Verbose.
-vv Very verbose.
--apply Really apply modifications.
-e PERLCODE Execute PERLCODE. (e.g. 's/a/b/g')
--from-charset=CS Source charset. (e.g. \"iso-8859-1\")
--to-charset=CS Destination charset. (e.g. \"utf-8\")
--unicode-normalize=NF Unicode normalization form. (e.g. \"KD\")
--basename Modifies only the last element of the path.
";
use Encode;
use Getopt::Long;
use Unicode::Normalize 'normalize';
use File::Basename;
use I18N::Langinfo qw(langinfo CODESET);
Getopt::Long::Configure ("bundling");
# ----------------------------------------------------------------------------------------------- #
# Our variables. #
# ----------------------------------------------------------------------------------------------- #
my $apply = 0;
my $verbose = 0;
my $help = 0;
my $debug = 0;
my $basename = 0;
my $unicode_normalize = "";
my @scripts;
my $from_charset = "";
my $to_charset = "";
my $codeset = "";
# ----------------------------------------------------------------------------------------------- #
# Get cmdline options. #
# ----------------------------------------------------------------------------------------------- #
$result = GetOptions ("apply" => \$apply,
"verbose|v+" => \$verbose,
"execute|e=s" => \@scripts,
"from-charset=s" => \$from_charset,
"to-charset=s" => \$to_charset,
"unicode-normalize=s" => \$unicode_normalize,
"basename" => \$basename,
"help|h|?" => \$help,
"debug" => \$debug);
# If not going to apply, then be verbose.
if (!$apply && $verbose == 0) {
$verbose = 1;
}
if ((($#scripts == -1)
&& (($from_charset eq "") || ($to_charset eq ""))
&& $unicode_normalize eq "")
|| ($#ARGV == -1) || ($help)) {
print $help_msg;
exit(0);
}
if (($to_charset ne "" && $from_charset eq "")
||($from_charset eq "" && $to_charset ne "")
||($to_charset eq "" && $from_charset eq "" && $unicode_normalize ne "")) {
$codeset = langinfo(CODESET);
$to_charset = $codeset if $from_charset ne "" && $to_charset eq "";
$from_charset = $codeset if $from_charset eq "" && $to_charset ne "";
}
# ----------------------------------------------------------------------------------------------- #
# Composes the filter function using the @scripts array and possibly other options. #
# ----------------------------------------------------------------------------------------------- #
$f = "sub filterfunc() {\n my \$s = shift;\n";
$f .= " my \$d = dirname(\$s);\n my \$s = basename(\$s);\n" if ($basename != 0);
$f .= " for (\$s) {\n";
$f .= " $_;\n" foreach (@scripts); # Get scripts from '-e' opt. #
# Handle charset translation and normalization.
if (($from_charset ne "") && ($to_charset ne "")) {
if ($unicode_normalize eq "") {
$f .= " \$_ = encode(\"$to_charset\", decode(\"$from_charset\", \$_));\n";
} else {
$f .= " \$_ = encode(\"$to_charset\", normalize(\"$unicode_normalize\", decode(\"$from_charset\", \$_)));\n"
}
} elsif (($from_charset ne "") || ($to_charset ne "")) {
die "You can't use `from-charset' nor `to-charset' alone";
} elsif ($unicode_normalize ne "") {
$f .= " \$_ = encode(\"$codeset\", normalize(\"$unicode_normalize\", decode(\"$codeset\", \$_)));\n"
}
$f .= " }\n";
$f .= " \$s = \$d . '/' . \$s;\n" if ($basename != 0);
$f .= " return \$s;\n}\n";
print "Generated function:\n\n$f" if ($debug);
# ----------------------------------------------------------------------------------------------- #
# Evaluates the filter function body, so to define it in our scope. #
# ----------------------------------------------------------------------------------------------- #
eval $f;
# ----------------------------------------------------------------------------------------------- #
# Main loop, which passes names through filters and renames files. #
# ----------------------------------------------------------------------------------------------- #
foreach (@ARGV) {
$old_name = $_;
$new_name = filterfunc($_);
if ($old_name ne $new_name) {
if (!$apply or (rename $old_name, $new_name)) {
print "`$old_name' => `$new_name'\n" if ($verbose);
} else {
print "Cannot rename `$old_name' to `$new_name'.\n";
}
} else {
print "`$old_name' unchanged.\n" if ($verbose > 1);
}
}
答案 16 :(得分:1)
答案 17 :(得分:0)
这对我使用regexp:
我希望将文件重命名为:
file0001.txt -> 1.txt
ofile0002.txt -> 2.txt
f_i_l_e0003.txt -> 3.txt
使用[az | _] + 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
警告,小心。
答案 18 :(得分:0)
我编写了这个脚本来搜索所有.mkv文件,递归地将找到的文件重命名为.avi。您可以根据自己的需要进行自定义。我添加了一些其他的东西,比如从文件路径获取文件目录,扩展名,文件名,只是因为你需要在将来引用某些东西。
find . -type f -name "*.mkv" | while read fp; do
fd=$(dirname "${fp}");
fn=$(basename "${fp}");
ext="${fn##*.}";
f="${fn%.*}";
new_fp="${fd}/${f}.avi"
mv -v "$fp" "$new_fp"
done;
答案 19 :(得分:0)
在文件列表上运行sed
表达式的通用脚本(将sed
solution与rename
solution结合使用):
#!/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*
答案 20 :(得分:0)
您也可以使用以下脚本。它很容易在终端上运行......
//一次重命名多个文件
for file in FILE_NAME*
do
mv -i "${file}" "${file/FILE_NAME/RENAMED_FILE_NAME}"
done
示例: - 强>
for file in hello*
do
mv -i "${file}" "${file/hello/JAISHREE}"
done
答案 21 :(得分:0)
另一个可能的parameter expansion:
for f in fgh*; do mv -- "$f" "jkl${f:3}"; done
答案 22 :(得分:0)
通用命令是
find /path/to/files -name '<search>*' -exec bash -c 'mv $0 ${0/<search>/<replace>}' {} \;
其中 <search>
和 <replace>
应分别替换为您的源和目标。
作为针对您的问题量身定制的更具体示例(应从文件所在的同一文件夹中运行),上述命令如下所示:
find . -name 'gfh*' -exec bash -c 'mv $0 ${0/gfh/jkl}' {} \;
对于“试运行”,在 echo
之前添加 mv
,以便您查看生成的命令:
find . -name 'gfh*' -exec bash -c 'echo mv $0 ${0/gfh/jkl}' {} \;