【问题标题】:bash: how to change the basename only of a list of files [duplicate]bash:如何仅更改文件列表的基本名称[重复]
【发布时间】:2010-11-22 06:25:43
【问题描述】:

可能重复:
makefile: how to add a prefix to the basename?

我有很多文件(我从find bla -name "*.so" 获得),例如:

/bla/a1.so /bla/a2.so /bla/blo/a3.so /bla/blo/a4.so /bla/blo/bli/a5.so

我想将它们重命名为:

/bla/liba1.so /bla/liba2.so /bla/blo/liba3.so /bla/blo/liba4.so /bla/blo/bli/liba5.so

...即将前缀“lib”添加到基本名称

关于如何在 bash 中做到这一点的任何想法?

【问题讨论】:

  • 这不是重复的......另一个问题是询问如何使用 Make 来实现这一点,而这是询问如何直接在 bash 脚本中实现相同的目标
  • 投票重新开放,而不是欺骗。

标签: bash rename prefix


【解决方案1】:

类似的东西:

for a in /bla/a1.so /bla/a2.so /bla/blo/a4.so
do
  dn=$(dirname $a)
  fn=$(basename $a)
  mv "$a" "${dn}/lib${fn}"
done

应该这样做。当然,您可能想要添加代码以从文件中读取文件名列表,而不是在脚本中逐字列出它们。

【讨论】:

  • 感谢(我猜)亚伦添加引号,这是一个很好的观点。
  • 是的,当然,我忘记了 dirname 所以我看不到如何轻松分割路径...谢谢!尽管最后一行应该: mv $a $dn/lib$fn 否则,bash 会将 dn 和 fn 视为 shell 命令
  • +1 用于使用 $() 而不是反引号。
【解决方案2】:
find . -name "*.so" -printf "mv '%h/%f' '%h/lib%f'\n" | bash

代码将重命名当前目录和子目录中的文件以在 .so 文件名前附加“lib”。

不需要循环,因为find 已经完成了它的递归工作来列出文件。代码一一构建“mv”命令并执行它们。要查看“mv”命令而不执行它们,只需删除外壳部分“| bash”的管道即可。

find 的 printf 命令可以理解许多变量,这使得它具有很强的可扩展性。我只需要在这里使用两个:

  • %h:目录
  • %f: 文件名

如何测试它

先运行这个(什么都不做,只在屏幕上打印行):

find . -name "*.so" -printf "mv '%h/%f' '%h/lib%f'\n" | less -S

这将显示您的脚本将执行的所有命令。如果您对结果感到满意,只需在之后通过管道将其传递到 bash 而不是 less 来执行它。

find . -name "*.so" -printf "mv '%h/%f' '%h/lib%f'\n" | bash

【讨论】:

  • 您可能希望在 find 命令中添加适当的mindepthmaxdepth 并用引号保护文件和目录名称,以防它们[颤抖] 中有空格。 find . -mindepth 2 -maxdepth 2 -name "*.so" -printf "mv '%h/%f' '%h/lib%f'\n" | sh
  • 我同意引用,因此我更新了我的代码。
  • 这个解决方案有很多结果有问题吗?例如。达到最大命令长度或类似的东西?
  • 否,因为它会逐行打印。我已经更新了我的答案,以提供一种在试运行中对其进行测试的方法。
【解决方案3】:

while multiliner

基于 $nfm 的稍微更健壮和通用的解决方案(可能比您真正需要的更多)是

while IFS= read -r -u3 -d $'\0' FILE; do
    DIR=`dirname $FILE`;
    FILENAME=`basename $FILE`;
    mv $FILE ${DIR}/lib${FILENAME};
done 3< <(find bla -name *.so -print0 | sort -rz)

这是相当健壮的:

  • 读取 -u3 和 3
  • -print0 + IFS= + -d $'/0' 允许在文件名中使用换行符
  • sort -rz 首先重命名更深的路径,这样您甚至可以一次重命名目录和其中的文件

find -execdir + rename

如果不是因为 PATH 的烦恼,这将是完美的,请参阅:Find multiple files and rename them in Linux

【讨论】:

    【解决方案4】:

    试试mmv:

    cd /bla/
    mmv "*.so" "lib#1.so"
    

    mmv "*" "lib#1" 也可以,但不太安全)。

    如果您没有安装mmv,请获取它。

    【讨论】:

    • mmv 听起来很强大!感谢您的信息
    【解决方案5】:

    basename 和 dirname 是你的朋友 :)

    你想要这样的东西(请原谅我的 bash 语法 - 它有点生疏):

    for FILE in `find bla -name *.so` do
        DIR=`dirname $FILE`;
        FILENAME=`basename $FILE`;
        mv $FILE ${DIR}/lib${FILENAME};
    done
    

    被打败了!

    【讨论】:

      【解决方案6】:

      注意我已经注释掉了 mv 命令以防止任何意外的混乱

      for f in *
      do
          dir=`dirname "$f"`
          fname=`basename "$f"`
          new="$dir/lib$fname"
          echo "new name is $new"
          # only uncomment this if you know what you are doing
          # mv "$f" "$new" 
      done
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-26
        • 2018-10-16
        • 2022-06-27
        • 2023-02-20
        • 1970-01-01
        • 2018-02-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多