Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 从列表中删除重复的文件名,忽略目录_Bash_Shell_Unix - Fatal编程技术网

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

Bash 从列表中删除重复的文件名,忽略目录,bash,shell,unix,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/f

我正在运行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似乎没有提供匹配最后一个字段的选项,也不允许设置分隔符。有哪些解决方案?

使用awk,您可以:

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

我们在awk中构建一个可变路径。文件名由$NF(最后一个字段以/)表示。我们构建一个文件名数组(path1)及其关联路径。对于文件中的每个记录/行,将引用此数组以检查文件名是否有路径条目。如果存在条目,则忽略记录,从而停止任何复制,否则将使用awk打印路径,您可以执行以下操作:

awk -F\/ '{ path=""; if ( path1[$NF] == "" ) { print $0;path1[$NF]=$0 } }' filename
我们在awk中构建一个可变路径。文件名由$NF(最后一个字段以/)表示。我们构建一个文件名数组(path1)及其关联路径。对于文件中的每个记录/行,将引用此数组以检查文件名是否有路径条目。如果存在条目,则忽略记录,从而停止任何复制,否则将打印路径

Shortawk解决方案:

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

  • ![$NF]+
    -确保只输出唯一的文件名(包含在最后一列
    $NF

输出:

/path/to/number1/file1.txt
/path/to/number1/file2.txt
/path/to/number1/file3.txt
awk解决方案:

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

  • ![$NF]+
    -确保只输出唯一的文件名(包含在最后一列
    $NF

输出:

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

有一个使用纯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
#我们将有一个包含现有文件名作为密钥的集合。
声明-文件集
阅读全文时;做
fileName=“${fullPath##*/}”#basename
如果[!-n“${fileSet[$fileName]}”];然后#如果文件不在集合中。
echo$fullPath>>$FILEOUTPUT
文件集[$fileName]=1
fi
完成<$FILEINPUT

有一个使用纯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
#我们将有一个包含现有文件名作为密钥的集合。
声明-文件集
阅读全文时;做
fileName=“${fullPath##*/}”#basename
如果[!-n“${fileSet[$fileName]}”];然后#如果文件不在集合中。
echo$fullPath>>$FILEOUTPUT
文件集[$fileName]=1
fi
完成<$FILEINPUT

您不需要所有这些工作来构建
路径
,因为您只使用
路径$NF
,它与
$0
完全相同。注:for(in)可以而且几乎总是以与输入不同的顺序生成文件名;目前还不清楚这是否与本作品有关。@dave_thompson_085文件的顺序实际上对我来说并不重要。@dave_thompson_085,你提出了一个有效的观点,我修改了代码以简化并考虑排序。你不需要所有的工作来构建
path
,因为你只使用
path$NF
,这与
$0
完全相同。注:for(in)可以而且几乎总是以与输入不同的顺序生成文件名;不清楚这是否与此操作有关。@dave_thompson_085文件的顺序在我的情况下实际上并不重要。@dave_thompson_085,你提出了一个有效的观点,我修改了代码以简化并考虑顺序。你的示例输出与描述不匹配。@Williampersell也许我所说的令人困惑。我有成千上万的“文件列表”,其中包含一些文件的绝对路径。发现其中一些列表包含相同的文件,但路径不同(两个相同的文件)。我只想从列表中删除其中一个相同的文件,删除哪一个文件无关紧要,因为它们是相同的。您的示例输出与描述不匹配。@williampersell也许我说的有些混乱。我有成千上万的“文件列表”,其中包含一些文件的绝对路径。发现其中一些列表包含相同的文件,但路径不同(两个相同的文件)。我只想从列表中删除其中一个相同的文件,删除哪一个并不重要,因为它们是相同的。