Bash中的文件名比较

时间:2015-05-20 09:41:13

标签: bash

我有两个包含文件列表的文件。我需要检查第二个文件列表中缺少的文件。问题是我不必匹配全名,但只需要匹配文件名的最后19个字符。

E.g

MyFile123432 20150510230000.xlsx

MyFile999996的 20150510230000.xlsx

是相同的文件。

这是一个独特的问题,我不知道如何开始。请帮助。

4 个答案:

答案 0 :(得分:0)

首先,您可以使用comm来匹配确切的文件名,并获取不匹配的文件列表。然后你可以使用agrep。我从未使用它,但您可能会发现它很有用。

或者,作为最后一个选项,您可以执行暴力破解,并对第一个文件中的每一行搜索到第二个:

#!/bin/bash

# Iterate through the first file
while read LINE; do

    # Find the section of the filename that has to match in the other file
    CHECK_SECTION="$(echo "$LINE" | sed -nre 's/^.*([0-9]{14})\.(.*)$/\1.\2/p')"

    # Create a regex to match the filenames in the second file
    SEARCH_REGEX="^.*$CHECK_SECTION$"

    # Search...
    egrep "$SEARCH_REGEX" inputFile_2.txt

done < inputFile_1.txt

这里我假设文件名以14位数字结尾,在另一个文件中必须匹配,文件扩展名可能与文件不同,但也必须匹配:

MyFile12343220150510230000.xlsx
|  variable |   14digits |.ext

答案 1 :(得分:0)

基于awk的解决方案:

$ awk '
   {start=length($0) - 18;}
   NR==FNR{a[substr($0, start)]++; next;} #save last 19 characters for every line in file2
   {if(!a[substr($0, start)]) print $0;} #If that is not present in file1, print that line.
'  file2.list file.list

答案 2 :(得分:0)

因此,如果第一个文件是FILE1而第二个文件是FILE2,那么如果只是为了识别FILE2FILE1中不存在的文件以下应该做:

tmp1=$(mktemp)
tmp2=$(mktemp)
cat $FILE1 | rev | cut -c -19 | sort | uniq > ${tmp1}
cat $FILE2 | rev | cut -c -19 | sort | uniq > ${tmp2}
diff ${tmp1} ${tmp2} | rev
rm ${tmp1} ${tmp2}

简而言之,这会反转每一行上的字符,并为每个文件列表提取您感兴趣的部分,保存到临时文件。由于你没有说文件名的长度是否保证是恒定的,所以完成了字符的反转---我们唯一可以依赖的是最后19个字符是固定格式的(在这种情况下)虽然格式很容易推断,但它并不真正相关)。排序很重要,以便diff向您显示第一个 中第二个文件中没有的内容。

如果您确定FILE2只会丢失文件而不是相反(即FILE2FILE1中不存在diff中的文件),然后你可以通过移除diff ${tmp1} ${tmp2} | rev | grep -i xlsx | sed 's/[[:space:]]\+.*//' 引入的残骸来清理东西,所以最后一行变为:

grep

xlsx将输出限制为具有FILE1文件名的行,并且sed会删除从第一个空格开始的行上的所有内容。

当然,从技术上讲,这只会告诉您FILE2MyFile12343220150510230000.xlsx中存在时间戳分组文件组 - 据我所知,这是你在寻找什么(我对你的问题描述的理解是MyFile99999620150510230000.xlsxrev会有相同的内容)。如果文件名总是相同的长度(你后来肯定的话),则不需要FILE1,并且可以修改剪切命令以引用固定的字符位置。

在任何情况下,要获取最终文件列表,您必须使用“已清理”输出来过滤grep的内容;所以,修改上面的脚本使其包含“cleanup”命令,我们可以使用tmp1=$(mktemp) tmp2=$(mktemp) missing=$(mktemp) cat $FILE1 | rev | cut -c -19 | sort | uniq > ${tmp1} cat $FILE2 | rev | cut -c -19 | sort | uniq > ${tmp2} diff ${tmp1} ${tmp2} | rev | grep -i xlsx | sed 's/[[:space:]]\+.*//' > ${missing} grep -E "("`echo $(<${missing}) | sed 's/[[:space:]]/|/g'`")" ${tmp1} rm ${tmp1} ${tmp2} ${missing} 过滤所需的文件 - 然后整个脚本变为:

grep

扩展-E命令(FILE2)只为每个timestamp-plus-extension构建一个“或”正则表达式,并将其应用于第一个文件。当然,这是假设永远不会有FILE1而不是--child-silent-after-fork=yes中存在的时间戳组 - 如果 的话,那么“差异”输出处理“位需要更聪明一点。

答案 3 :(得分:0)

或者您可以使用标准coreutil工具:

for i in $(cat file1 file2 | sort | uniq -u); do 
    grep -q "$i" f1.txt && \
    echo "f2 missing '$i'" || \
    echo "f1 missing '$i'"
done

它将识别哪个文件中缺少哪些非公共条目。您也可以以任何您喜欢的方式操纵非常见的文件名,例如参数扩展/子串提取,子字符串删除或字符索引。