centos 如何查找和重命名多个文件?

z9smfwbn  于 2022-11-07  发布在  其他
关注(0)|答案(3)|浏览(214)

我有多个文件在多个目录,我必须重命名这些文件从小写到大写;文件扩展名可能会有所不同,并且需要使用小写(对于扩展名为大写的文件,也应该重命名)。
注:我有rename版本从util-linux的CentOS Linux 7。
我试过这个:

find /mydir -depth | xargs -n 1 rename -v 's/(.*)\/([^\/]*)/$1\/\U$2/' {} \;
find /mydir -depth | xargs -n 1 rename -v 's/(.*)\/([^\/]*)/$2\/\L$2/' {} \;

但它不工作,它什么也没改变,我没有输出。
我尝试了另一种解决方案:

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

这一个部分工作,但转换文件扩展名为大写太多。
关于如何保持/转换扩展名为小写有什么建议吗?
谢谢你,谢谢你

r7xajy2e

r7xajy2e1#

Perl rename的可能解决方案:

find /mydir -depth -type f -exec rename -v 's/(.*\/)?([^.]*)/$1\U$2/' {} +

问题中的命令有几个问题。
您似乎混淆了find-exec操作和xargs的语法。
第一个
xargs版本在文件名包含空格时会出现问题。
如果将\;替换为+,则会将多个文件名传递给rename的一个调用。
只有Perl版本的rename命令才支持替换命令。您可能必须安装此版本。请参阅Get the Perl rename utility instead of the built-in rename
替换在我的测试中不起作用。我成功地使用

rename -v 's/(.*\/)?([^.]*)/$1\U$2/' file ...

第一个组(.*\/)?可以选择匹配一个带有尾随/的字符序列。这用于复制未更改的目录。
第二组([^.]*)匹配除.之外的字符序列。
这是文件名中 first 点(如果有)之前的部分,将转换为大写。如果文件名有多个扩展名,则所有扩展名都将保持不变,例如:
Path/To/Foo.Bar.Baz -〉Path/To/FOO.Bar.Baz

wwodge7n

wwodge7n2#

rename-独立解(将findmv一起使用)

您可以使用以下命令重命名目录中的所有文件:

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的rename相关解决方案

rename -f 'y/A-Z/a-z/' *

此命令将大写字符更改为小写字符。-f选项允许覆盖现有文件,但这不是必要的。

6mzjoqzu

6mzjoqzu3#

建议使用awk技巧来生成所有必需的mv命令:

awk '{f=$0;split($NF,a,".");$NF=tolower(a[1])"."toupper(a[2]);print "mv "f" "$0}' FS=/ OFS=/ <<< $(find . -type f)

检查结果,并同时运行所有mv命令:

bash <<< $(awk '{f=$0;split($NF,a,".");$NF=tolower(a[1])"."toupper(a[2]);print "mv "f" "$0}' 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 = $0; # 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" "$0; 
}

测试:

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

相关问题