【问题标题】:renaming file name in unix在 unix 中重命名文件名
【发布时间】:2022-01-03 13:13:22
【问题描述】:

我们需要将文件从 filename.dat.dat.dat 重命名为 filename.dat。我们有很多文件具有相同类型的名称,扩展名为 .dat.dat.dat

使用以下脚本:

cd /home/riya
for file in filename.dat.dat.dat
do
echo $file
new = "${file:0:12}"
echo $new
mv $file $new
done

给出以下错误:

riya.ksh[5]: "${file:0:12}": bad substitution

【问题讨论】:

  • 我想这不是unix问题,而是ksh问题? Unix 有很多 shell,${file:0:12} 表达式不是传统的 shell 表达式。
  • 那你能告诉我如何重命名文件

标签: unix rename ksh


【解决方案1】:

除非这些文件名全部由八个字符组成,后面跟着.dat 重复三次,否则最好使用正则表达式来修改它们。像sed 这样的实用程序可以毫无问题地做到这一点。

您的问题有点不清楚这些 .dat 文件的位置,但如果它们都在同一个目录中,那么这应该可以:

for f in *.dat.dat.dat
  do
    g=$(echo $f | sed s/\\.dat\\.dat//)
    echo "$f -> $g" ; mv $f $g
  done

【讨论】:

  • 非常感谢....解决了我的问题
【解决方案2】:

@r3mainer:您的解决方案是可能的,但它的可行性取决于有多少这样的文件:使用 sed(或任何其他外部程序 - awk,tr,...)将需要产生一个完整的新子- 进程及其环境对系统造成很大负担。幸运的是,您的 sed 脚本的功能可以通过使用“参数替换”在 shell 中实现。

@riva:首先,你的代码不能工作,因为变量赋值不允许有空格:

 new = "${file:0:12}"    # wrong!
 new="${file:0:12}"      # correct!

即使是第二个也只能根据您使用的外壳而起作用。例如,ksh88(AIX 中的默认 shell)不会,ksh93(Linux 中唯一的 ksh 版本,在 AIX 中名为“增强型 Korn shell”)会理解这一点。

不过,@r3mainer 的批评仍然成立:这只有在所有文件名都保证为 8 个字符长的情况下才有效。相反,您可以使用参数替换来获得您想要的:

 new="filename.dat.dat.dat"
 echo ${new%%.dat*}          # this will yield "filename"
 new="${new%%.dat*}.dat"     # this will yield "filename.dat"

扩展${variable%%pattern}variable 内容的末尾切掉pattern(最长可能的形式,“贪婪匹配”)。由于模式是“.dat*”,这意味着从第一个(任意多个)“.dat”序列开始的所有内容都被剪切。然后在末尾添加一个“.dat”。

此外,请注意,您不应将“for-loops”用于此类活动。 "find" 是用于这种目的的命令:

 find /some/directory -type f -name "*.dat" -print |\
 while read FILE ; do
      mv "${FILE}" "${FILE%%.dat*}.dat"
 done

【讨论】: