从列表中删除重复的文件名,忽略目录

时间:2017-07-03 19:56:30

标签: bash shell unix

我正在运行Linux并编写BASH脚本。

我有一个文本文件,每行都有一个绝对文件路径。我发现有时我的一个文本文件将具有相同的文件,但列在不同的路径下。我想删除包含相同文件的这些行,这样文件只表示一次。

例如,如果我有:

/path/to/number1/file1.txt
/path/to/number1/file2.txt
/path/to/number1/file3.txt
/path/to/number2/file3.txt

我希望生成的文件包含:

/path/to/number1/file1.txt
/path/to/number1/file2.txt
/path/to/number1/file3.txt

路径长度是可变的(例如,文件名不能保证在字段4中)。

我曾尝试使用uniq的类似问题的先前解决方案,但uniq似乎没有提供匹配最后一个字段的选项,也不允许设置分隔符。有什么解决方案?

3 个答案:

答案 0 :(得分:2)

awk 解决方案:

awk -F'/' '!a[$NF]++' file
  • -F'/' - 将/视为字段分隔符

  • !a[$NF]++ - 确保仅输出唯一文件名(包含在最后一栏$NF中)

输出:

/path/to/number1/file1.txt
/path/to/number1/file2.txt
/path/to/number1/file3.txt

答案 1 :(得分:1)

使用awk,你可以这样做:

awk -F\/ '{ path=""; if ( path1[$NF] == "" ) { print $0;path1[$NF]=$0 } }' filename

我们在awk中构建一个变量路径。文件名由$ NF表示(最后一个字段用/分隔)。我们使用相关路径构建一个文件名(path1)数组。对于文件中的每个记录/行,引用此数组以检查文件名是否存在路径条目。如果有条目,则忽略记录,因此停止任何复制,否则打印路径

答案 2 :(得分:1)

使用纯粹的bash内置解决方案是一种富有表现力的解决方案。

将关联数组作为集合,您可以通过不断检查密钥是否已被使用来实现,在这种情况下,您只需继续循环。

# We will have a set which will contain existing filenames as keys.
declare -A fileSet

while read fullPath; do 
    fileName="${fullPath##*/}" # basename
    if [ ! -n "${fileSet[$fileName]}" ]; then # If the file is not already in the set.
        echo $fullPath >> $FILEOUTPUT
        fileSet[$fileName]=1
    fi
done < $FILEINPUT