仅根据部分文件名列出唯一文件

仅根据部分文件名列出唯一文件

例如,我有许多类似于下面输出的文件,我试图获取所有唯一文件名的列表,但忽略“-”右侧的字符。我尝试过ls -la | grep ....- | sort --unique一些变化,但这并没有给出我需要的输出

4855-00160880.psi
4855-00160980.ps
4855-00160980.psi
5355-00160880.ps
5355-00160880.psi
5355-00160980.ps
5355-00160980.psi
5855-00160880.ps
5855-00160880.psi
5855-00160980.ps
5855-00160980.psi
5855-00160A80.ps
5855-00160A80.psi

理想情况下,我希望输出显示类似的内容

4855
5355
5855

答案1

自从你真的不想解析ls,这应该可以解决问题:

find . -type f -maxdepth 1 -exec basename "{}" \; | cut -d'-' -f1 | sort -u

答案2

这个怎么样?

printf "%-4.4s\n" ????-* | uniq

shell 按字母顺序扩展通配符并将结果作为参数传递给printf.格式字符串将每个参数截断为四个字符并添加换行符。现在剩下的就是删除相邻的重复项。

如果您不知道连字符之前的位数,但您有一个想法,您可以循环一些候选者:

for expr in '??' '???' '????' '?????'  # Quoted (!)
do
    printf "%-${#expr}.${#expr}\n" $expr-* |  # Unquoted!
    uniq
done

这使用仅 Bash 的参数扩展 $[#var}从而获得 的字符串长度$var

请注意引用通配符以避免它们在循环初始化中扩展的技巧,然后在循环内使用未加引号的变量(这在大多数其他情况下是禁忌)。

答案3

值得添加-type f到 DopeGhoti 的答案中,以避免出现虚假.结果。

find . -maxdepth 1 -exec basename "{}" \; | cut -d'-' -f1 | sort -u
.
4855
5355
5855
find . -maxdepth 1 -type f -exec basename "{}" \; | cut -d'-' -f1 | sort -u
4855
5355
5855
$

如果希望与您最初的尝试保持相似,您可以使用这个(不好,因为它解析ls!)

ls -1 | grep ^....-  | cut -c1-4 | sort --unique

基于 awk 的解决方案,仍在解析 ls

ls -1 | awk -F- '{print $1}' | sort --unique

在每种情况下都不需要进行排序,因为ls输出已经排序,所以可以只使用uniq.

ls -1 | awk -F- '{print $1}' | uniq

基于sed的解决方案

ls -1 | sed 's/-.*//' | uniq

find / sed 避免解析 ls 的解决方案

find . -type f -printf "%f\n" | sed 's/-.*//g' | sort --unique

如果“-”之前总是 4 位数字,那么这非常优雅

find . -type f -printf "%.4f\n" | sort -u

答案4

zsh

myfiles=(*-*(.))
print -rl -- ${(u)myfiles[@]%%-*}

这会将至少包含一个破折号的所有常规文件名保存在数组中。然后,它对数组的每个元素使用参数扩展来删除第一个破折号和后面的所有内容。任何重复的元素都会通过标志删除(u)
要也选择隐藏文件,请使用myfiles=(*-*(.D))

相关内容