我有很多重复的文件。这些文件看起来像这样:
dsc_0364_5723957929_o.jpg
dsc_0364_5294988157_o.jpg
dsc_0365_2464873748_o.jpg
dsc_0365_2853758327_o.jpg
....
我想删除具有相同前缀的第二个文件(有时是第三个)。我怎么做?
答案1
您可以gawk
与find
and一起使用xargs
:
find -maxdepth 1 -type f -name 'dsc*jpg' -print0 |
gawk 'BEGIN { RS=ORS="\0" ; FS="_" } seen[$2]++' |
xargs -0 rm
请注意,使用 NUL 作为记录分隔符是 AFAIK仅在 GNU awk 中受支持( gawk
)。
答案2
如果所有文件都遵循相同的模式,则此解决方案有效:string_string_string_string.string
.我的意思是文件名中必须有三个_
才能获得其前缀。例如,有文件名:dsc_0360_5294988157_o.jpg
我想获取它的前缀dsc_0360
。
以下脚本应该可以工作:
#! /usr/bin/env bash
lastPrefix=''
for i in ./* ; do
prefix=${i%_*_*}
if [[ $prefix == $lastPrefix ]];then
rm $i
else
lastPrefix=$prefix
fi
done
通过该行,prefix=${i%_*_*}
我获取文件名的前缀,并比较之前是否已经设置了相同的前缀,如果是,则应该删除该文件。
您可能需要更改for i in ./* ;
您的工作目录:for i in /path/to/your/working_directory ;
答案3
您将需要使用关联数组来跟踪您已经见过的文件名前缀。例如:
#!/bin/bash
# define $seen as an associative array (-A).
declare -A seen
for f in dsc_* ; do
# derive a value for $prefix by removing the last
# two _ sections from $f, e.g. remove '_5723957929_o.jpg'
prefix=${f%_*_*}
# test if "$seen"'s element for this "$prefix" is empty:
if [ -z "${seen[$prefix]}" ] ; then
# if it is, then we haven't seen this prefix before, so
# we need to remember it.
seen[$prefix]="$f"
# optional debugging output. delete or comment out if
# not needed.
echo "seen[$prefix] = $f"
else
# Dry-run showing which files would be deleted.
# remove the echo to actually delete it. Optionally
# add -v for verbose output.
echo rm -f "$f"
fi
done
当在包含示例文件名的目录中运行时,它会生成以下输出:
seen[dsc_0364] = dsc_0364_5294988157_o.jpg
rm -f dsc_0364_5723957929_o.jpg
seen[dsc_0365] = dsc_0365_2464873748_o.jpg
rm -f dsc_0365_2853758327_o.jpg
如果它在没有调试输出的情况下运行并echo rm -f
替换rm -fv
为详细输出,则会产生以下输出
removed 'dsc_0364_5723957929_o.jpg'
removed 'dsc_0365_2853758327_o.jpg'
如果没有-v
,它会删除文件但根本不产生任何输出。