bash-3.00$ cat f.txt
-rw-r--r-- 1 mukesh other 102 Nov 5 18:32 f1.txt
-rw-r--r-- 1 mukesh other 19 Nov 5 18:32 f2.txt
-rw-r--r-- 1 mukesh other 204 Nov 5 18:32 f3.txt //DUPLICATE
-rw-r--r-- 1 mukesh other 204 Nov 6 18:32 f3.txt //DUPLICATE
-rw-r--r-- 1 mukesh other 204 Nov 6 18:32 f100.txt
假设我在名为 f.txt 的文件中列出了上述文件名。我想列出所有有重复的文件名(仅文件名),显示重复的文件名和重复的数量。
例如:在上面的列表中,f3.txt 有一个重复项,并且总共找到了 2 个 f3.txt 文件名。
答案1
正如您提到的awk
,这是一个解决方案:
awk '{d[$9]++}END{for(f in d)if(d[f]>1)print d[f],f}' f.txt
如果您还有名称中包含空格字符的文件,则需要一些解决方法:
awk '{f=$9;for(i=10;i<=NF;i++)f=f" "$i;d[f]++}END{for(f in d)if(d[f]>1)print d[f],f}' f.txt
请注意,上述解决方法可能会失败,例如在处理符号链接时。毕竟,解析ls
输出并不是一个好主意。如果可能的话,最好以其他方式生成 f.txt。 (例如find
或stat
,您可以更好地控制列表格式。)
答案2
这是 pure 的解决方案bash
,因为您的问题清楚地表明您有 bash 3 可用:
#!/bin/bash
if [[ -t 0 ]]; then
printf '%s\n' 'No input!'
exit 1
fi
while read -ra _file; do
_file="${foo[*]:8}"
for _file_name_already_known in "${_files[@]}"; do
if [[ ${_file_name_already_known} == "${_file}" ]]; then
for _file_name_already_printed in "${_already_printed[@]}"; do
[[ ${_file_name_already_printed} == "${_file}" ]] && continue 3
done
printf '%s\n' "${_file}"
_already_printed+=( "${_file}" )
fi
done
_files+=( "${_file}" )
done
输出:
$ ./lsdups < f.txt
f3.txt
运行为./lsdups < file
.
但请记住,ls
输出并不是最好的选择。http://mywiki.wooledge.org/ParsingLs阐述了您不应该这样做的一些原因。