如何删除给定范围内的编号文件?


16

我有folderA一些文件,这些文件的编号顺序以开头a_000000。我想要做的是删除一个从特定编号开始的文件:假设a_000750直到this中的文件结尾folderA。任何人都可以建议使用shell脚本执行此操作吗?


我可以假定所有这些文件名都具有6位后缀吗?
muru

是的,他们是:)他们从a_000000开始直到某个数字
Tak

5
rm a_000[89]* a_0007[5-9]*
Rinzwind 2014年

@Rinzwind您能解释一下此命令吗?
2014年

2
@ user1460166 a_000[89]*包含每个以a_0008或开头的文件a_0009,并a_0007[5-9]*包含每个以a_00075到9之间的数字开头且后跟任何数字的文件。
muru 2014年

Answers:


35

假设您知道或可以猜测范围的结束,则可以使用括号扩展

rm a_{000750..000850}

上面的代码将删除a_000750和a_000850(含)之间的101个文件(并抱怨引用不存在的文件的文件名)。如果有太多文件,请使用find

find . -name 'a_*' | while read file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

在这里,find只需列出所有匹配的文件a_*。该列表被传递到while循环,在循环中,每个文件名都被读入变量$file。然后,使用bash的字符串操作功能,如果数字部分(find打印文件为./file${file#./a_}则仅打印数字)等于000750或大于数字,则删除文件。的-v是就在那里,所以你可以看到被拆除哪些文件。

请注意,以上假定文件名合理。如果您的名字可以包含空格,换行符或其他奇怪的字符,请改用以下方法:

find . -name 'a_*' -print0 | while IFS= read -rd '' file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

为什么要避免[[
muru 2014年

1
@muru为什么使用它?例如,[[这里并没有简化事情[[ "${file#./a_}" > 000749 ]],甚至没有使其更短。我不喜欢使用不必要的语法,而且这种语法甚至可以在更简单的shell中使用,例如dash
terdon 2014年

因为可以[[更好地处理空格和怪异现象(我也不在乎>)。
muru 2014年

1
@muru是的,但是[如果您像我一样引用变量,那很好,它可以在更多的shell上工作并且更简单。
terdon 2014年

如果你坚持。不是我的问题。
muru

3

您可以执行以下操作:

find . -regextype posix-extended -iregex './a_[0-9]{6}' -execdir bash -c '[[ ${1##./a_} > 000750 ]] && echo $1' "removing: " {} \;

要么:

find . -regextype posix-extended -iregex './a_[0-9]{6}' | sort | sed '0,/000750/d' | xargs echo

第一种方法采用固定前缀,将其剥离并检查该值。

第二种方法假定一个固定长度的后缀(和一个共同的固定前缀)并依赖于这一事实。并且,虽然201之前来31安装词典,它之前不会031

使用echo命令进行测试,一旦确定列出正确的文件,请rm改用。


他们都不在工作:/
Tak Tak

@ user1460166啊,可能是由于正则表达式匹配。我会更新。
muru 2014年

还是行不通。顺便说一句,文件是.png :)
Tak

@ user1460166您能说它怎么不工作吗?
muru 2014年

我打开终端,cd到文件夹,然后复制您的行并将其粘贴,但是文件并未删除
Tak

0

POSIX Shell解决方案

terdon的第一个解决方案 依赖于括号扩展,这是bashand 的属性ksh,但是不能在标准/bin/shshell中使用,在Ubuntu上,标准shell 被符号链接到/bin/dash

如果您必须依靠/bin/sh脚本的可移植性,通常有两种方法可以解决此问题。一种可能是通过遍历。就cd folderA从那里跑rm a_*。另一种方法是while <CONDITION>;do ...done在外壳语言中使用C样式的循环替代方法,并使用以下格式格式化数字printf

$ sh -c 'i=0;while [ $i -le 750 ]; do filename=$(printf "a_%06d" $i);echo "$filename";i=$((i+1)) ;done'

请注意,这里我使用echo。当您准备删除文件时,请echo "$filename"rm ./"$filename"或替换rm -- "$filename"。还要注意,这应该在您已经cd进入所需目录时执行。

(ab)使用awk

Awk是一种不错的类似于C的语言,可以通过两种方式为我们提供帮助:(1)我们可以使用for循环生成文件名并通过sprintf函数对其进行格式设置,以及(2)通过system()命令删除所述文件,这将传递我们生成的文件名和rm命令至/bin/sh

awk 'BEGIN{for(i=0;i<=750;i++){filename=sprintf("a_%06d",i);system("rm "filename);} }'

佩尔

继续使用“生成”文件名的可移植方法的思想,我们可以在Perl中执行相同的操作:

perl -le 'for(0..750){$fd=sprintf("a_%06d",$_);unlink($fd)}'

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.