删除重复的文件扩展名

时间:2014-03-09 20:12:58

标签: regex linux bash sed

我有成千上万的文件名为filename.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz

我正在使用像这个find . -name "*.gz*"这样的find命令找到这些文件,并使用-exec或管道到xargs并有一些魔法命令来清理这个混乱,所以我最终得到了文件名。 GZ

有人请帮我提出这个魔术命令,删除.gz不需要的实例。我曾尝试使用sed 's/\.gz//'sed 's/(\.gz)//'进行试验,但它们似乎不起作用(或者说更诚实,我对sed不是很熟悉)。顺便说一下,我不必使用sed,欢迎任何有助于解决这个问题的解决方案: - )

8 个答案:

答案 0 :(得分:4)

使用find和awk的一种方式:

find $(pwd) -name '*.gz'|awk '{n=$0;sub(/(\.gz)+$/,".gz",n);print "mv",$0,n}'|sh 

注意:

  • 我假设您的文件名中没有特殊的字符(如空格......)。如果有,你需要在mv命令中引用文件名。
  • 我添加了$(pwd)以获取找到名称的绝对路径。
  • 您可以移除结尾|sh以检查生成的mv ... .... cmd(如果正确)。
  • 如果一切正常,请添加|sh以执行mv

见示例:

enter image description here

答案 1 :(得分:0)

您可以使用

ls a.gz.gz.gz |sed -r 's/(\.gz)+/.gz/'

或没有正则表达式标志

ls a.gz.gz.gz |sed 's/\(\.gz\)\+/.gz/'

答案 2 :(得分:0)

ls *.gz | perl -ne '/((.*?.gz).*)/; print "mv $1 $2\n"'

它将打印shell命令来重命名文件,它不会执行这些命令。这很安全。要执行它,您可以将其保存到文件并执行,或者只是管道到shell:

ls *.gz | ... | sh

sed非常适合替换文件中的文本

答案 3 :(得分:0)

find . -name "*.gz.gz" | 
 while read f; do echo mv "$f" "$(sed -r 's/(\.gz)+$/.gz/' <<<"$f")"; done

这只预览重命名(mv)命令;删除echo以执行实际重命名。

  • 处理当前目录 tree 中的匹配文件,如在OP中(而不仅仅是当前目录中直接的文件)。
  • 限制与至少以 2 .gz扩展名结尾的文件的匹配(以免不必要地处理仅以一个结尾的文件)。
  • 使用sed确定新名称时,请确保子字符串.gz不仅匹配文件名中的任何位置,而只是作为.gz扩展名的连续序列的一部分文件名的 end
  • 处理带有特殊字符的文件名。例如嵌入空格正确(除了带有嵌入换行符的文件名。)

答案 4 :(得分:0)

您可以使用bash字符串替换来执行此操作:

for file in *.gz.gz; do
    mv "${file}" "${file%%.*}.gz"
done 

答案 5 :(得分:0)

使用bash字符串替换:

for f in *.gz.gz; do
    mv "$f" "${f%%.gz.gz*}.gz"
done 

这是对jaypal的好答案的略微修改(如果你的任何文件的某个句点作为其名称的一部分,如foo.c.gz.gz),则会失败。 (我的也不完美)注意使用双引号,它可以防止文件名出现“坏”字符,例如空格或星号。

如果您希望使用find处理整个目录树,则变体为:

find . -name \*.gz.gz | \
while read f; do
    mv "$f" "${f%%.gz.gz*}.gz"
done

如果您挑剔且需要处理带有嵌入换行符的文件名,请将while read更改为while IFS= read -r -d $'\0',然后将-print0添加到find;见How do I use a for-each loop to iterate over file paths output by the find utility in the shell / Bash?

但是这个重命名是个好主意吗?你的filename.gz.gz是如何创建的? gzip有意外防止这样做。如果你通过像gzip -c $1 > $1.gz这样的东西绕过这些东西,埋在一些脚本中,那么重命名这些文件会让你感到悲伤。

答案 6 :(得分:0)

这可能适合你(GNU sed):

echo *.gz | sed -r 's/^([^.]*)(\.gz){2,}$/mv -v & \1\2/e'

答案 7 :(得分:0)

重命名的另一种方式:

find . -iname '*.gz.gz' -exec rename -n 's/(\.\w+)\1+$/$1/' {} +

如果对结果感到满意,请删除-n(干运行)选项。