首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >以更快的方式列出具有相似名称的文件(使用bash)?

以更快的方式列出具有相似名称的文件(使用bash)?
EN

Stack Overflow用户
提问于 2018-03-13 13:55:08
回答 3查看 353关注 0票数 1

我有一个包含超过20K个文件的目录,所有文件都有一个随机数字前缀(例如12345--name.jpg)。我想找到具有相似名称的文件,并删除除一个以外的所有文件。我不关心是哪一个,因为它们是重复的。

查找我使用过的重复名称

代码语言:javascript
复制
find . -type f \( -name "*.jpg" \) | | sed -e 's/^[0-9]*--//g' | sort | uniq -d

作为for/next循环的列表。

要查找除一个之外的所有要删除的内容,我当前使用

代码语言:javascript
复制
rm $(ls -1 *name.jpg | tail -n +2)

这个操作相当慢。我想加快速度。有什么建议吗?

EN

回答 3

Stack Overflow用户

发布于 2018-03-13 14:59:15

我会这样做。

*请注意,您正在处理 rm 命令,因此请确保您有现有目录的备份,以防出现问题。

  1. 创建备份目录并备份现有文件。完成检查是否所有文件都在那里。

mkdir bkp_dir;cp *.jpg /bkp_dir

  • Create另一个临时目录,我们将为每个相似的名字只保存一个文件。所以所有唯一的文件名都会在这里。

$ mkdir tmp $ for i in $(ls -1 *.jpg|sed‘s/^[:digit:].*--(.*.jpg)/\1/’|*.jpg|sed|uniq);do cp $(ls -1|grep "$i"|head -1) tmp/ ;done

*命令的解释在最后。执行后,如果获得了文件的唯一实例,请签入/tmp目录。

  1. 从主目录中删除所有*.jpg文件。再次声明,在执行rm命令之前,请确认所有文件都已备份。

rm *.jpg

  • 备份临时目录中的唯一实例。

cp tmp/*..jpg .

步骤2中命令的解释。

用于获取步骤2的唯一文件名的

  • 命令将为

for i in $(ls -1 *.jpg|sed 's/^[[:digit:]].*--\(.*\.jpg\)/\1/'|sort|uniq);do cp $(ls -1|grep "$i"|head -1) tmp/ ;done

  • $(ls -1 *.jpg|sed 's/^[[:digit:]].*--\(.*\.jpg\)/\1/'|sort|uniq)将获得唯一的文件名,如

  • for i in $(...);do cp $(ls -1|grep "$i"|head -1) tmp/ ;done将为每个文件名复制一个文件到file1.jpg , file2.jpg /file1.jpg , file2.jpg
票数 0
EN

Stack Overflow用户

发布于 2018-03-13 15:36:01

假设不涉及子目录和文件名中的空格:

代码语言:javascript
复制
find . -type f -name "*.jpg" | sed -e 's/^[0-9]*--//' | sort | uniq -d > namelist 
removebutone () { shift; echo rm "$@"; }; cat namelist | while read n; do removebutone "*--$n"; done 

或者,可读性更好:

代码语言:javascript
复制
removebutone () { 
  shift
  echo rm "$@"
}
cat namelist | while read n; do removebutone "*--$n"; done 

Shift从$*中取出第一个参数。

请注意,名称parmeter周围的括号是多余的,并且sed之前不应该有两个管道。也许你还有其他的东西,需要被覆盖。

如果它看起来很有希望,当然,你必须去掉'rm‘前面的'echo’。

票数 0
EN

Stack Overflow用户

发布于 2018-03-13 15:48:10

You should not be using ls in scripts,并且没有理由像在用户未知的回复中那样使用单独的文件列表。

代码语言:javascript
复制
keepone () {
    shift
    rm "$@"
}
keepone *name.jpg

如果您正在运行find来标识您无论如何都要隔离的文件,那么遍历目录两次是低效的。直接过滤来自find的输出。

代码语言:javascript
复制
find . -type f -name "*.jpg" |
awk '{ f=$0; sub(/^[0-9]*--/, "", f); if (a[f]++) print }' |
xargs echo rm

如果结果与您期望的一样,请取出echo

另外,对于只能匹配一次的正则表达式,sed/g标志是无用的。该标志表示替换一行上的所有匹配项,而不是一行上的第一个匹配项,但如果只能有一个匹配项,则第一个匹配项等同于所有。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49249173

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档