巨大なCSVで重複したファイル名を見つけるためのスクリプトの最適化

巨大なCSVで重複したファイル名を見つけるためのスクリプトの最適化

スクリプトによって生成された1 MBから6 GBのサイズのCSVファイルが複数あり、inotifyイベントリストの形式は次のとおりです
timestamp;fullpath;event;size

これらのファイルの形式は次のとおりです。

timestamp;fullpath;event;size
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_OPEN;2324
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_ACCESS;2324
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_CLOSE_NOWRITE;2324
1521540649.02;/home/workdir/quad_list_14.json;IN_OPEN;2160
1521540649.03;/home/workdir/quad_list_14.json;IN_ACCESS;2160
1521540649.03;/home/workdir/quad_list_14.json;IN_CLOSE_NOWRITE;2160
1521540649.03;/home/workdir/ScienceXMLIn/masterbias_list.asc;IN_OPEN;70
1521540649.03;/home/workdir/ScienceXMLIn/masterbias_list.asc.1;IN_OPEN;80
1521540649.03;/home/workdir/ScienceXMLIn/masterbias_list.asc.2;IN_OPEN;70
1521540649.03;/home/workdir/otherfolder/quad_list_14.json;IN_OPEN;2160
1521540649.03;/home/workdir/otherfolder/quad_list_14.json;IN_CLOSE_NOWRITE;2160

私の目標は、別のフォルダに表示される同じ名前のファイルを識別することです。
この例では、ファイルがおよびquad_list_14.jsonすべてに表示されます。/home/workdir/otherfolder/home/workdir/

私が望む出力は簡単です。複数のフォルダに表示されるファイルのリストです。この場合、次のようになります。

quad_list_14.json

そのために、私は次のような小さなコードを書いた。

#this line cut the file to only get unique filepath
PATHLIST=$(cut -d';' -f 2 ${1} | sort -u)
FILENAMELIST=""

#this loop build a list of basename from the list of filepath
for path in ${PATHLIST}
do
    FILENAMELIST="$(basename "${path}")
${FILENAMELIST}"
done

#once the list is build, I simply find the duplicates with uniq -d as the list is already sorted
echo "${FILENAMELIST}" | sort | uniq -d

自宅ではこのコードを使用しないでください。残念です。このスクリプトを次のオンラインユーザーに置き換える必要があります。

#this get all file path, sort them and only keep unique entry then
#remove the path to get the basename of the file 
#and finally sort and output duplicates entry.
cut -d';' -f 2 ${1} | sort -u |  grep -o '[^/]*$' | sort | uniq -d

私の問題はまだ残っています。ファイル数が多いため、SSDでは少なくとも0.5秒かかりますが、別のフォルダで重複したファイル名を見つけるには最大45秒(私の本番ディスクはそれほど高速ではありません)がかかります。

このコードをより効率的にするために改善する必要があります。私の唯一の制限は、ファイルをRAMに完全にロードできないことです。

ベストアンサー1

次のAWKスクリプトは、あまりにも多くのメモリを使用せずにこの問題を解決する必要があります。

#!/usr/bin/awk -f

BEGIN {
    FS = ";"
}

{
    idx = match($2, "/[^/]+$")
    if (idx > 0) {
        path = substr($2, 1, idx)
        name = substr($2, idx + 1)
        if (paths[name] && paths[name] != path && !output[name]) {
            print name
            output[name] = 1
        }
        paths[name] = path
    }
}

各ファイルのパスと名前を抽出し、各名前の最後のパスを保存します。以前に別のパスを見た場合、すでに出力されていない場合はその名前を出力します。

おすすめ記事