我有一个包含超过20K文件的目录,所有文件都带有随机数前缀(例如12345 - name.jpg)。我想找到具有相似名称的文件并删除除一个之外的所有文件。我不在乎哪一个,因为它们是重复的。
要查找重复的名称,我使用
rm $(ls -1 *name.jpg | tail -n +2)
作为for / next循环的列表。
要查找除一个以外的所有内容,我目前正在使用
separate reducer
此操作非常慢。我想加快速度。有什么建议吗?
答案 0 :(得分:0)
我会这样做。
*请注意,您正在处理rm
命令,因此请确保备有现有目录,以防出现问题。
创建备份目录并备份现有文件。 完成后,请检查所有文件是否都在那里。
mkdir bkp_dir;cp *.jpg /bkp_dir
创建另一个临时目录,我们将为每个相似的名称保留所有只有1个文件。所以所有独特的文件名都在这里。
$ mkdir tmp
$ for i in $(ls -1 *.jpg|sed 's/^[[:digit:]].*--\(.*\.jpg\)/\1/'|sort|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)
将获得唯一的文件名,例如file1.jpg , file2.jpg
for i in $(...);do cp $(ls -1|grep "$i"|head -1) tmp/ ;done
会将每个文件名的一个文件复制到tmp /目录。
答案 1 :(得分:0)
假设没有涉及子目录且没有涉及空格的文件名:
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从$ * off获取第一个参数。
请注意,名称parmeter周围的parens是超级的,并且sed之前不应该有两个管道。也许你还有别的东西需要被覆盖。
如果它看起来很有希望,你当然要删除'rm'前面的'echo'。
答案 2 :(得分:0)
You should not be using ls
in scripts并且没有理由使用单独的文件列表,例如在userunknown的回复中。
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
。
顺便说一下,/g
的{{1}}标志对于只能匹配一次的正则表达式是无用的。该标志表示替换行上的所有出现而不是行上的第一个出现,但如果只有一个,则第一个等同于全部。