我有成千上万的文件名为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,欢迎任何有助于解决这个问题的解决方案: - )
答案 0 :(得分:4)
使用find和awk的一种方式:
find $(pwd) -name '*.gz'|awk '{n=$0;sub(/(\.gz)+$/,".gz",n);print "mv",$0,n}'|sh
注意:
$(pwd)
以获取找到名称的绝对路径。|sh
以检查生成的mv ... ....
cmd(如果正确)。|sh
以执行mv
见示例:
答案 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
以执行实际重命名。
.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
(干运行)选项。