【问题标题】:How to use sed to change file extensions?如何使用 sed 更改文件扩展名?
【发布时间】:2021-08-02 18:22:04
【问题描述】:

我必须做一个 sed 行(也在 Linux 中使用管道)来更改文件扩展名,所以我可以做一些 mv *.1stextension *.2ndextension 之类的 mv *.txt *.c。问题是我不能使用批处理或 for 循环,所以我必须使用管道和 sed 命令来完成。

【问题讨论】:

  • 为什么不能使用循环?你应该说清楚!你这样做是作为家庭作业的一部分吗?
  • 我当然是,我没有提到,但我认为由于限制而众所周知

标签: linux bash sed


【解决方案1】:

你可以使用字符串操作

filename="file.ext1"
mv "${filename}" "${filename/%ext1/ext2}"

或者如果你的系统支持,你可以使用rename

更新

你也可以这样做

mv ${filename}{ext1,ext2}

称为大括号展开

【讨论】:

  • 我想知道我们是否允许用户rename ...它在大多数Linux系统中都可用
  • 谢谢,但我不能使用任何批处理或脚本语句,我只能使用我的命令行、sed 和管道
  • 您的输入到底是什么?你期望什么样的输出?如果只有sed 允许,我认为您不能重命名文件。
  • @user2113403: for filename in *.1stextension; do mv "${filename}" "${filename/%1stextension/2ndextension}"; done 可以处理一堆文件。不需要sed
  • POSIX:${filename%.ext1}.ext2
【解决方案2】:

sed 用于操作文件的内容,而不是文件名本身。我的建议:

rename 's/\.ext/\.newext/' ./*.ext

或者,这个existing question 应该会有所帮助。

【讨论】:

  • 我不得不在 Makefile 中将 .c 替换为 .o。这解决了我的问题,谢谢。
【解决方案3】:

这可能有效:

find . -name "*.txt" | 
sed -e 's|./||g' | 
awk '{print "mv",$1, $1"c"}' | 
sed -e "s|\.txtc|\.c|g" > table;
chmod u+x table;
./table

我不知道你为什么不能使用循环。它让生活更轻松:

newex="c";  # Give your new extension
for file in *.*;  # You can replace with *.txt instead of *.*
do 
 ex="${file##*.}";    # This retrieves the file extension
 ne=$(echo "$file" | sed -e "s|$ex|$newex|g"); # Replaces current with the new one
 echo "$ex";echo "$ne";
 mv "$file" "$ne";
done

【讨论】:

  • 我不应该使用任何循环或句子,只使用管道、命令行和 sed
【解决方案4】:

您可以使用find 查找所有文件,然后将其传送到while read 循环中:

$ find . -name "*.ext1" -print0 | while read -d $'\0' file
do
   mv $file "${file%.*}.ext2"
done

${file%.*}小的右模式过滤器% 标记要从右侧删除的模式(匹配可能的最小 glob 模式),.* 是模式(最后一个 . 后跟 . 之后的字符)。

-print0 将使用NUL 字符而不是\n 分隔文件名。 -d $'\0' 将读入由NUL 字符分隔的文件名。这样,带有空格、制表符、\n 或其他古怪字符的文件名将被正确处理。

【讨论】:

  • 这怎么不是循环? OP 不想要任何循环!
  • 这是一个管道。正如 OP 所说“所以我必须用 pipes 和 sed 命令 来完成这一切”。我不确定 OP 对 for 有什么问题,但 for 可能很麻烦,因为它解析循环参数的方式。不幸的是,OP 没有提供太多他们在做什么的信息。有了更多信息,我可以给出更好的答案。
  • 同意你的观点,OP没有提供足够的信息,为什么不循环!
【解决方案5】:

您可以尝试以下选项

选项 1 find 以及 rename

find . -type f -name "*.ext1" -exec rename -f 's/\.ext1$/ext2/' {} \;

选项 2 find 以及 mv

find . -type f -name "*.ext1" -exec sh -c 'mv -f $0 ${0%.ext1}.ext2' {} \;

注意:观察到rename 不适用于许多终端

【讨论】:

  • @iamauser 尝试使用选项 2 mv 如果 rename 不起作用。即使我不确定为什么rename 不适用于许多终端。对我来说,它适用于ubuntu,但不适用于RHEL
【解决方案6】:

另一种仅使用 sed 和 sh 的解决方案

printf "%s\n" *.ext1 | 
sed "s/'/'\\\\''/g"';s/\(.*\)'ext1'/mv '\''\1'ext1\'' '\''\1'ext2\''/g' | 
sh

为了更好的性能:只创建一个进程

perl -le '($e,$f)=@ARGV;map{$o=$_;s/$e$/$f/;rename$o,$_}<*.$e>' ext2 ext3

【讨论】:

    【解决方案7】:

    这应该可以工作

    mv $file $(echo $file | sed -E -e 's/.xml.bak.*/.xml/g' | sed -E -e 's/.\///g')
    

    输出

    abc.xml.bak.foobar -> abc.xml
    

    【讨论】:

      猜你喜欢
      • 2017-11-21
      • 2011-08-22
      • 1970-01-01
      • 2021-10-19
      • 1970-01-01
      • 2011-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多