我有两个包含文件列表的文件。我需要检查第二个文件列表中缺少的文件。问题是我不必匹配全名,但只需要匹配文件名的最后19个字符。
E.g
MyFile123432 20150510230000.xlsx
和
MyFile999996的 20150510230000.xlsx
是相同的文件。
这是一个独特的问题,我不知道如何开始。请帮助。
答案 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
,那么如果只是为了识别FILE2
中FILE1
中不存在的文件以下应该做:
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
只会丢失文件而不是相反(即FILE2
中FILE1
中不存在diff
中的文件),然后你可以通过移除diff ${tmp1} ${tmp2} | rev | grep -i xlsx | sed 's/[[:space:]]\+.*//'
引入的残骸来清理东西,所以最后一行变为:
grep
xlsx
将输出限制为具有FILE1
文件名的行,并且sed会删除从第一个空格开始的行上的所有内容。
当然,从技术上讲,这只会告诉您FILE2
但MyFile12343220150510230000.xlsx
中存在时间戳分组文件组 - 据我所知,这是你在寻找什么(我对你的问题描述的理解是MyFile99999620150510230000.xlsx
和rev
会有相同的内容)。如果文件名总是相同的长度(你后来肯定的话),则不需要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
它将识别哪个文件中缺少哪些非公共条目。您也可以以任何您喜欢的方式操纵非常见的文件名,例如参数扩展/子串提取,子字符串删除或字符索引。