我有一个包含超过20K个文件的目录,所有文件都有一个随机数字前缀(例如12345--name.jpg)。我想找到具有相似名称的文件,并删除除一个以外的所有文件。我不关心是哪一个,因为它们是重复的。
查找我使用过的重复名称
find . -type f \( -name "*.jpg" \) | | sed -e 's/^[0-9]*--//g' | sort | uniq -d作为for/next循环的列表。
要查找除一个之外的所有要删除的内容,我当前使用
rm $(ls -1 *name.jpg | tail -n +2)这个操作相当慢。我想加快速度。有什么建议吗?
发布于 2018-03-13 14:59:15
我会这样做。
*请注意,您正在处理 rm 命令,因此请确保您有现有目录的备份,以防出现问题。
mkdir bkp_dir;cp *.jpg /bkp_dir
$ 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目录。
*.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。发布于 2018-03-13 15:36:01
假设不涉及子目录和文件名中的空格:
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 或者,可读性更好:
removebutone () {
shift
echo rm "$@"
}
cat namelist | while read n; do removebutone "*--$n"; done Shift从$*中取出第一个参数。
请注意,名称parmeter周围的括号是多余的,并且sed之前不应该有两个管道。也许你还有其他的东西,需要被覆盖。
如果它看起来很有希望,当然,你必须去掉'rm‘前面的'echo’。
发布于 2018-03-13 15:48:10
You should not be using ls in scripts,并且没有理由像在用户未知的回复中那样使用单独的文件列表。
keepone () {
shift
rm "$@"
}
keepone *name.jpg如果您正在运行find来标识您无论如何都要隔离的文件,那么遍历目录两次是低效的。直接过滤来自find的输出。
find . -type f -name "*.jpg" |
awk '{ f=$0; sub(/^[0-9]*--/, "", f); if (a[f]++) print }' |
xargs echo rm如果结果与您期望的一样,请取出echo。
另外,对于只能匹配一次的正则表达式,sed的/g标志是无用的。该标志表示替换一行上的所有匹配项,而不是一行上的第一个匹配项,但如果只能有一个匹配项,则第一个匹配项等同于所有。
https://stackoverflow.com/questions/49249173
复制相似问题