我需要知道如何在文件夹中找到一个或多个具有相同文件名的文件(括号内的文件除外)并删除文件较小的文件。我不在乎它是 GUI 应用程序还是终端命令。
例如:亚当斯一家(美国版)/亚当斯一家(世界版)/亚当斯一家(欧洲版)(英、法、德)
答案1
你可以考虑这样的事情
创建一个数组数组,其中第一个索引是通过删除任意数量的尾随文件名前缀获得的公共文件名前缀空格括号组序列,第二个索引是完整文件名,其值是文件大小。然后,对于每个前缀,按大小降序对完整文件名进行排序,并输出第二个。这将为您提供以下文件列表:不是每个公共前缀的最大值。
实现这一点的一种方法是使用 GNU awk,例如
$ stat --printf '%s\034%n\0' -- *\(*\)* | gawk '
BEGIN {
RS="\0"
FS=SUBSEP
}
{
pfx = gensub(/( [(][^)]*[)])+$/,"", "1", $2)
a[pfx][$2] = $1+0
}
END {
for (p in a){
n = asorti(a[p], b, "@val_num_desc")
for(i=2; i<=n; i++) printf "%s\0", b[i]
}
}' | xargs -r0 -n1 -- echo
(请注意,如果任何文件名包含 ASCII FS 字符(八进制值为 034),则此操作将失败)。
如果输出了正确的文件,那么您可以用 替换echo
(或者,为了提高效率,-n1
和echo
)rm
。
如果只有一个具有给定前缀的文件,则不会输出该前缀的任何内容(因此不会删除任何文件)。如果具有给定前缀且最大大小相同的多个文件,则除了一个文件之外的所有文件都将被输出以进行删除 - 如果在这种情况下您想保留特定文件(例如,按字典顺序排列的第一个文件名),则需要进行额外的排序。
答案2
在 zsh 中,你可以使用一个指示函数,如果存在具有相同前缀且更大的文件,则该函数返回 TRUE,然后使用该函数作为glob 限定符。
具有相同前缀的多个文件具有相同的最大大小的情况需要特别考虑。如果您使用“大小严格大于”作为唯一条件,则指示器将为每个文件返回 FALSE,并且将保留所有文件。另一方面,如果您使用“大小大于或等于”,则它将为每个文件返回 TRUE,并且不会保留任何文件。如果您想要任何其他结果,那么您将需要一个决胜局 - 以下使用文件名的词典权重,即它保留在当前语言环境中排序最先的文件。您可能希望修改决胜局以使用其他标准,例如文件的修改时间。
#!/usr/bin/zsh
zmodload -F zsh/stat b:zstat
myind () {
local -A s
local fname1=$REPLY
local fname fsize fsize1
local pat=${fname1/% \(*\)/ \\(*\\)}
zstat -L -H s -- $fname1
fsize1=$s[size]
for fname (${~pat}) {
[[ $fname -ef $fname1 ]] && continue
zstat -L -H s -- $fname
fsize=$s[size]
# select for deletion if a larger file of the same prefix exists
if (( fsize > fsize1 )); then
return 0
# tiebreaker - retain lexicographically first file
# (might consider changing to most recent)
elif (( fsize == fsize1 )) && [[ $fname < $fname1 ]]; then
return 0
fi
}
return 1
}
print -r -C1 -- *\(*\)*(.N+myind)
将上述脚本保存到文件中,使用 使其可执行chmod +x path/to/name-of-script
,然后以 运行它path/to/name-of-script
。例如,如果它保存在您当前的工作目录中:
chmod +x ./name-of-script
./name-of-script
按照所写,该脚本仅打印出要删除的文件的名称。如果它能满足您的要求,那么您可以将该print
命令更改为rm
命令。
答案3
阅读man find xargs stat sort tail cut
并做一些类似的事情未经测试:
find . -type f -name 'Addams Family, The*' -print0 | \
xargs -0 -r stat --format="%s %N" | \
sort -rn | \
tail --lines=+2 | \
cut "-d " -f2- | \
xargs echo rm
echo
当您对文件列表满意时,从最后一行删除。