如何查找和重命名多个文件
How can i find and rename multiple files
我在多个目录中有多个文件,我必须将这些文件从小写重命名为大写;文件扩展名可能不同,需要小写(对于大写扩展名的文件也应该重命名)。
注意:我在 CentOS Linux7 上有来自 util-linux
的 rename
版本。
我试过这个:
find /mydir -depth | xargs -n 1 rename -v 's/(.*)\/([^\/]*)/\/\U/' {} \;
find /mydir -depth | xargs -n 1 rename -v 's/(.*)\/([^\/]*)/\/\L/' {} \;
但它不起作用,它没有任何改变,我没有输出。
我尝试了另一种解决方案:
for SRC in `find my_root_dir -depth`
do
DST=`dirname "${SRC}"`/`basename "${SRC}" | tr '[A-Z]' '[a-z]'`
if [ "${SRC}" != "${DST}" ]
then
[ ! -e "${DST}" ] && mv -T "${SRC}" "${DST}" || echo "${SRC} was not renamed"
fi
done
这个部分有效,但也将文件扩展名转换为大写。
关于如何 keep/transform 将扩展名改为小写有什么建议吗?
谢谢!
rename
-独立解(使用find
和mv
)
您可以使用以下命令重命名目录中的所有文件:
for i in $( ls | grep [A-Z] ); do mv -i $i `echo $i | tr 'A-Z' 'a-z'`; done
第一部分 (for i in $( ls | grep [A-Z] );
) 查找所有大写字符并执行直到所有文件都被“扫描”。
第二部分(``)将所有大写字符转换为小写字符。
Perl-basedrename
依赖解
rename -f 'y/A-Z/a-z/' *
此命令将大写字符更改为小写字符。 -f
选项允许覆盖现有文件,但没有必要。
Perl 的可能解决方案 rename
:
find /mydir -depth -type f -exec rename -v 's/(.*\/)?([^.]*)/\U/' {} +
问题中的命令有几个问题。
您似乎混淆了 find
的 -exec
操作和 xargs
的语法。
find /mydir -depth -type f -exec rename -v 'substitution_command' {} \;
find /mydir -depth -type f| xargs -n 1 rename -v 'substitution_command'
xargs
版本在文件名包含 space.
时存在问题
如果将 \;
替换为 +
,多个文件名将传递给 rename
.
的一次调用
仅 Perl 版本的 rename
命令支持替换命令。您可能必须安装此版本。参见 Get the Perl rename utility instead of the built-in rename
替换在我的测试中不起作用。我成功使用
rename -v 's/(.*\/)?([^.]*)/\U/' file ...
第一组 (.*\/)?
可选择匹配带有尾随 /
的字符序列。这个是用来复制目录不变的。
第二组 ([^.]*)
匹配除 .
.
之外的字符序列
这是 第一个 点(如果有)之前的文件名部分,它将被转换为大写。如果文件名有多个扩展名,则全部保持不变,例如
Path/To/Foo.Bar.Baz
-> Path/To/FOO.Bar.Baz
建议使用 awk
的技巧来生成所有必需的 mv
命令:
awk '{f=[=10=];split($NF,a,".");$NF=tolower(a[1])"."toupper(a[2]);print "mv "f" "[=10=]}' FS=/ OFS=/ <<< $(find . -type f)
检查结果,运行 所有 mv
命令一起:
bash <<< $(awk '{f=[=11=];split($NF,a,".");$NF=tolower(a[1])"."toupper(a[2]);print "mv "f" "[=11=]}' FS=/ OFS=/ <<< $(find . -type f))
awk
脚本script.awk
解释
BEGIN { # preprocessing configuration
FS="/"; # set awk field separtor to /
OFS="/"; # set awk output field separtor to /
}
{ # for each line in input list
filePath = [=12=]; # save the whole filePath in variable
# fileName is contained in last field $NF
# split fileName by "." to head: splitedFileNameArr[1] and tail: splitedFileNameArr[2]
split($NF,splitedFileNameArr,".");
# recreate fileName from lowercase(head) "." uppercase(tail)
$NF = tolower(splitedFileNameArr[1]) "." toupper(splitedFileNameArr[2]);
# generate a "mv" command from original filePath and regenerated fileName
print "mv "filePath" "[=12=];
}
测试:
mkdir {a1,B2}/{A1,b2} -p; touch {a1,B2}/{A1,b2}/{A,b}{b,C}.{c,D}{d,C}
find . -type f
./a1/A1/Ab.cC
./a1/A1/Ab.cd
./a1/A1/Ab.DC
./a1/A1/Ab.Dd
./B2/b2/AC.DC
./B2/b2/AC.Dd
.....
./B2/b2/bC.cd
./B2/b2/bC.DC
./B2/b2/bC.Dd
awk -f script.awk <<< $(find . -type f)
.....
mv ./a1/b2/Ab.cd ./a1/b2/ab.CD
mv ./a1/b2/Ab.DC ./a1/b2/ab.DC
mv ./a1/b2/Ab.Dd ./a1/b2/ab.DD
mv ./B2/A1/bC.Dd ./B2/A1/bc.DD
.....
mv ./B2/b2/bC.DC ./B2/b2/bc.DC
mv ./B2/b2/bC.Dd ./B2/b2/bc.DD
bash <<< $(awk -f script.awk <<< $(find . -type f))
find . -type f
我在多个目录中有多个文件,我必须将这些文件从小写重命名为大写;文件扩展名可能不同,需要小写(对于大写扩展名的文件也应该重命名)。
注意:我在 CentOS Linux7 上有来自 util-linux
的 rename
版本。
我试过这个:
find /mydir -depth | xargs -n 1 rename -v 's/(.*)\/([^\/]*)/\/\U/' {} \;
find /mydir -depth | xargs -n 1 rename -v 's/(.*)\/([^\/]*)/\/\L/' {} \;
但它不起作用,它没有任何改变,我没有输出。
我尝试了另一种解决方案:
for SRC in `find my_root_dir -depth`
do
DST=`dirname "${SRC}"`/`basename "${SRC}" | tr '[A-Z]' '[a-z]'`
if [ "${SRC}" != "${DST}" ]
then
[ ! -e "${DST}" ] && mv -T "${SRC}" "${DST}" || echo "${SRC} was not renamed"
fi
done
这个部分有效,但也将文件扩展名转换为大写。
关于如何 keep/transform 将扩展名改为小写有什么建议吗?
谢谢!
rename
-独立解(使用find
和mv
)
您可以使用以下命令重命名目录中的所有文件:
for i in $( ls | grep [A-Z] ); do mv -i $i `echo $i | tr 'A-Z' 'a-z'`; done
第一部分 (for i in $( ls | grep [A-Z] );
) 查找所有大写字符并执行直到所有文件都被“扫描”。
第二部分(``)将所有大写字符转换为小写字符。
Perl-basedrename
依赖解
rename -f 'y/A-Z/a-z/' *
此命令将大写字符更改为小写字符。 -f
选项允许覆盖现有文件,但没有必要。
Perl 的可能解决方案 rename
:
find /mydir -depth -type f -exec rename -v 's/(.*\/)?([^.]*)/\U/' {} +
问题中的命令有几个问题。
您似乎混淆了 find
的 -exec
操作和 xargs
的语法。
find /mydir -depth -type f -exec rename -v 'substitution_command' {} \;
find /mydir -depth -type f| xargs -n 1 rename -v 'substitution_command'
xargs
版本在文件名包含 space.
如果将 \;
替换为 +
,多个文件名将传递给 rename
.
仅 Perl 版本的 rename
命令支持替换命令。您可能必须安装此版本。参见 Get the Perl rename utility instead of the built-in rename
替换在我的测试中不起作用。我成功使用
rename -v 's/(.*\/)?([^.]*)/\U/' file ...
第一组 (.*\/)?
可选择匹配带有尾随 /
的字符序列。这个是用来复制目录不变的。
第二组 ([^.]*)
匹配除 .
.
这是 第一个 点(如果有)之前的文件名部分,它将被转换为大写。如果文件名有多个扩展名,则全部保持不变,例如
Path/To/Foo.Bar.Baz
-> Path/To/FOO.Bar.Baz
建议使用 awk
的技巧来生成所有必需的 mv
命令:
awk '{f=[=10=];split($NF,a,".");$NF=tolower(a[1])"."toupper(a[2]);print "mv "f" "[=10=]}' FS=/ OFS=/ <<< $(find . -type f)
检查结果,运行 所有 mv
命令一起:
bash <<< $(awk '{f=[=11=];split($NF,a,".");$NF=tolower(a[1])"."toupper(a[2]);print "mv "f" "[=11=]}' FS=/ OFS=/ <<< $(find . -type f))
awk
脚本script.awk
解释
BEGIN { # preprocessing configuration
FS="/"; # set awk field separtor to /
OFS="/"; # set awk output field separtor to /
}
{ # for each line in input list
filePath = [=12=]; # save the whole filePath in variable
# fileName is contained in last field $NF
# split fileName by "." to head: splitedFileNameArr[1] and tail: splitedFileNameArr[2]
split($NF,splitedFileNameArr,".");
# recreate fileName from lowercase(head) "." uppercase(tail)
$NF = tolower(splitedFileNameArr[1]) "." toupper(splitedFileNameArr[2]);
# generate a "mv" command from original filePath and regenerated fileName
print "mv "filePath" "[=12=];
}
测试:
mkdir {a1,B2}/{A1,b2} -p; touch {a1,B2}/{A1,b2}/{A,b}{b,C}.{c,D}{d,C}
find . -type f
./a1/A1/Ab.cC
./a1/A1/Ab.cd
./a1/A1/Ab.DC
./a1/A1/Ab.Dd
./B2/b2/AC.DC
./B2/b2/AC.Dd
.....
./B2/b2/bC.cd
./B2/b2/bC.DC
./B2/b2/bC.Dd
awk -f script.awk <<< $(find . -type f)
.....
mv ./a1/b2/Ab.cd ./a1/b2/ab.CD
mv ./a1/b2/Ab.DC ./a1/b2/ab.DC
mv ./a1/b2/Ab.Dd ./a1/b2/ab.DD
mv ./B2/A1/bC.Dd ./B2/A1/bc.DD
.....
mv ./B2/b2/bC.DC ./B2/b2/bc.DC
mv ./B2/b2/bC.Dd ./B2/b2/bc.DD
bash <<< $(awk -f script.awk <<< $(find . -type f))
find . -type f