Оптимизация сценария для поиска дубликатов файлов в огромном CSV

openvpn - самый простой маршрут для всего и вы можете подключиться к серверу openvpn через прокси-сервер носков

Измените скрипт openvpn для подключения через порт носков 1234, добавив эти две строки:

 socks-proxy localhost 1234
 socks-proxy-retry

Это может быть полезно, если протокол openvpn блокируется как и в некоторых более угнетающих странах. Как правило, прокси носков устанавливается для каждого приложения. Вышеупомянутое решение требует как сервера openvpn, так и сервера shadowsocks.

-121--84459-

Терминалы передают байты, а не ключи. Такие ключи, как Ctrl + ', должны кодироваться как последовательности байтов. Помимо печатаемых символов без модификатора или только с помощью Shift , большинство ключей не имеют соответствующих символов и вместо этого передаются в виде escape-последовательностей, начиная с escape-символа (символа со значением байта 27, который можно записать как \e в строках Emacs). Но у многих ключей нет традиционной стандартной escape-последовательности, и многие терминалы либо не передают эти ключи, либо пропускают информацию об модификаторах (передавая Ctrl + ' как только символ ' ).

Некоторые терминалы позволяют настраивать управляющие последовательности для каждого ключа. В Terminal.app это можно сделать с помощью настроек клавиатуры .

Для Ctrl + ' выберите \033 [39; 5 ~ или \033 [27; 5; 39 ~ : это два новых стандарта, либтермкей Для получения дополнительной информации см. Проблемы с вводом клавиш при использовании терминала .

Emacs преобразует escape-последовательности во внутреннее представление ключа через input-decode-map или local-function-key-map (или function-key-map перед Emacs 23). Поместите любой из них в свой init-файл:

(define-key input-decode-map "\033[39;5~" [(control ?\')])
(define-key input-decode-map "\033[27;5;39~" [(control ?\')])

-121--185237-

С помощью GNU tar (найденного в не встроенных Linux и Cygwin) можно применить регулярную замену выражения к путям при добавлении членов в архив или при их извлечении с помощью опции -трансформа .

tar -xf foo.tar --transform='s!^/home/mydir/dir1/!!'

При использовании * BSD tar (включая OSX) существует аналогичная опция, называемая -s .

tar -xf foo.tar -s '!^/home/mydir/dir1/!!'

POSIX имеет команду pax с той же опцией, что и BSD tar.

pax -r 

4
18.03.2019, 05:46
3 ответа

Следующий скрипт 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
    }
}

Он извлекает путь и имя каждого файла и сохраняет последний увиденный путь для каждого имени. Если он ранее видел другой путь, он выводит имя, если только он уже не вывел его.

3
27.01.2020, 20:49

Основная проблема с вашим кодом заключается в том, что вы собираете все имена путей в переменную, а затем выполняете цикл для вызова basename. Это делает его медленным.

Цикл также проходит через раскрытие переменной без кавычек ${PATHLIST}, что было бы неразумно, если имена путей содержат пробелы или символы оболочки. Вbash(или других оболочках, которые его поддерживают ), вместо этого можно было бы использовать массив.

Предложение:

$ sed -e '1d' -e 's/^[^;]*;//' -e 's/;.*//' file.csv | sort -u | sed 's#.*/##' | sort | uniq -d
quad_list_14.json

Первый sedвыбирает пути (и отбрасывает строку заголовка ). Это также может быть записано как awk -F';' 'NR > 1 { print $2 }' file.csvили как tail -n +2 file.csv | cut -d ';' -f 2.

sort -uдает нам уникальные пути, а следующий sedдает нам базовые имена. Окончательный sortс uniq -dв конце говорит нам, какие базовые имена дублируются.

Последнее sed 's#.*/##', которое дает вам базовые имена, напоминает расширение параметра ${pathname##*/}, которое эквивалентно $( basename "$pathname" ). Он просто удаляет все до и включая последний /в строке.

Основное отличие от вашего кода заключается в том, что вместо цикла, который вызывает basenameнесколько раз, используется один sedдля создания базовых имен из списка путей.


Альтернатива просмотру только IN_OPENзаписей:

sed -e '/;IN_OPEN;/!d' -e 's/^[^;]*;//' -e 's/;.*//' file.csv | sort -u | sed 's#.*/##' | sort | uniq -d
4
27.01.2020, 20:49

Спасибо вам обоим за ответы и спасибо Исааку за комментарии.
Я взял весь ваш код и поместил его в скриптstephen.awkkusa.shи isaac.sh, после чего я провел небольшой тест, подобный этому:

for i in $(ls *.csv)
do
    script.sh $1
done

Командой timeсравниваю и вот результат:

stephen.awk

real    2m35,049s
user    2m26,278s
sys     0m8,495s

stephen.awk:обновлено /IN _OPEN/ перед вторым блоком

real    0m35,749s
user    0m15,711s
sys     0m4,915s

куса.ш

real    8m55,754s
user    8m48,924s
sys     0m21,307s

Обновление с включенным фильтромIN_OPEN:

real    0m37,463s
user    0m9,340s
sys     0m4,778s

Примечание:
Хотя правильно, у меня было много пустых строк, выведенных с помощью sed, ваш скрипт был единственным таким.

isaac.sh

grep -oP '^[^;]*;\K[^;]*' file.csv | sort -u | grep -oP '.*/\K.*' | sort | uniq -d
real    7m2,715s
user    6m56,009s
sys     0m18,385s

С включенным фильтромIN_OPEN:

real    0m32,785s
user    0m8,775s
sys     0m4,202s

мой сценарий

real    6m27,645s
user    6m13,742s
sys     0m20,570s

@Stephen, вы явно выиграли, с очень впечатляющим сокращением времени в 2,5 раза.

Хотя, немного подумав, я пришел к другой идее: что, если я буду смотреть только на событие OPEN file, это уменьшит сложность, и вы не предполагаете получить доступ к файлу или записать его, не открыв его сначала, поэтому я так и сделал. что:

#see I add grep "IN_OPEN" to reduce complexity
PATHLIST=$(grep "IN_OPEN" "${1}" | cut -d';' -f 2 | sort -u)
FILENAMELIST=""
for path in ${PATHLIST}
do
    FILENAMELIST="$(basename "${path}")
${FILENAMELIST}"
done
echo "${FILENAMELIST}" | sort | uniq -d

С этой единственной модификацией, которая дала мне тот же результат, я получаю это timeзначение:

real    0m56,412s
user    0m27,439s
sys     0m9,928s

И я уверен, что есть много других вещей, которые я мог бы сделать

1
27.01.2020, 20:49

Теги

Похожие вопросы