Сценарий Bash/awk для ввода и вывода файла CSV

Во-первых, если в rsync и есть такая опция, я о ней не знаю и не могу найти ее на странице руководства. Это досадно, так как это быстро предоставит то, что вам нужно, и предположительно для любого возможного rsyncварианта использования.

Во-вторых, я думаю, что если бы кто-то попытался сделать это с существующими опциями rsync (в основном --сухой -запуск в сочетании с избытком возможных комбинаций контрольной суммы, дата -была бы -новее, дата -стала -старше, файл -должен -быть -удаленным, до бесконечности )потребуется несколько проходов rsync, по одному для каждой возможной причины, по которой файл может получить rsyncизд. Это кажется громоздким для ваших целей.

Если вы можете работать с инструментом, который сравнивает два дерева и сообщает о различиях и интерполирует его вывод в соответствии с вашими потребностями, тогда mtreeможет подойти для ваших нужд.

mtreeспециально разработан для сравнения двух деревьев каталогов и сообщения о различиях.

На исходном компьютере создайте спецификацию mtree (, включая хэш sha256 )желаемого исходного дерева:

# mtree -K sha256 -cp /my_path > my_path.mtree

Затем rsyncпросмотрите дерево и запустите mtree на удаленной машине, чтобы увидеть, совпадает ли путь дерева удаленных каталогов /remote _с локальным путем /my _:

# rsync -a --delete /my_path/ remote:/remote_path/
# ssh remote mtree -p /remote_path < my_path.mtree && echo match
match

Теперь давайте немного повозимся с удаленным деревом. Короче говоря, я создал целевой файл farkle, которого не существует в источнике, удалил файл file.txtи изменил метку времени в файле data.txt.

# ssh remote mtree -p remote_path < my_path.mtree || echo fail
.:      modification time (Wed Apr 17 10:49:32 2019, Wed Apr 17 11:55:10 2019)
extra: farkle
data.txt: 
        modification time (Wed Apr 17 10:45:02 2019, Wed Apr 17 11:56:27 2019)
foo:    size (32, 29)
        modification time (Tue Apr 16 10:16:44 2019, Wed Apr 17 11:53:18 2019)
        sha256digest (0x6082aa7261362c4c71c82adf492bc724de53a5814e64b233c43c6775efeb1dd0, 0x2d2537ea27c27dfb2c1690c51c652b9ada32adc29a91b732c24939dcff371cd6)
./file.txt missing
fail

mtreeсообщает вам, что:

  • farkleсуществует в пункте назначения, но не в источнике; это было бы удаляется, если вы укажете --удалить в командной строке rsync.
  • data.txtне изменился ни по содержимому (, ни по хэшу sha256 ), ни по размеру, но более новая временная метка; копирование, основанное только на контрольной сумме, может не -повторно передать файл, а также rsyncне передать только «более новые» файлы, поскольку файл назначения теперь новее, чем исходный.
  • file.txtотсутствует на целевом хосте и, предположительно, rsyncбудет передано при следующем запуске, если не будет какого-либо критерия исключения.

Таким образом, это не совсем дает вам прямое объяснение от rsync о том, почему он копирует или не копирует то, что, по вашему мнению, должно, но действительно дает вам жесткий, поддающийся проверке отчет о том, что на самом деле происходит в отношении локальных и удаленных деревьев каталогов.

Если вы методично сохраните выходной файл my_path.mtree, например, включив в имя файла отметку даты, вы также можете запустить mtreeна локальном компьютере, чтобы сравнить существующее дерево путей /my _с предыдущим запуском. (вчерашний? на прошлой неделе? ), чтобы увидеть, не изменилось ли что-то локально, чего вы, возможно, не ожидали.

mtreeвключен в некоторые дистрибутивы Unix,но если у вас отсутствует mtree, мне удалось установить версию Арчи Коббса с GitHub .

1
03.10.2020, 00:03
4 ответа
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972

Для вывода в файл с именем output-fileи одновременного отображения в STDOUT:

$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data | tee output-file
bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48

Или просто выводить в тот же файл:

$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data > output-file
3
18.03.2021, 23:01

Чтобы получить разницу в датах, вы можете использовать эту небольшую функцию bash

Используйте следующие номера для своих нужд

  • #Чтобы получить Дни разница :86400
  • #Чтобы получить Годы разница :31536000

Функция удара

datediff() {
  current_date=$(date -d "$1" +%s)
  birth_date=$(date -d "$2" +%s)
  echo $(( (current_date - birth_date) / 31536000)) Years
}

Использование:

datediff '9/28/2020' '1/1/1999'

Выход:

 21 years
0
18.03.2021, 23:01

Чтобы выполнить более точные вычисления времени, вы можете использовать gawkфункции времени и строки(по предложению @AdminBee ). Использование входных данных как:

$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972

Вы можете получить разницу во времени в днях между настоящим моментом и датой, указанной в каждой строке, с помощью:

$ awk -F, 'BEGIN{today=systime()} 
           {print $0 "," int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))}' \
           data | tee output-file

 bob,wag,06/13/1958,22755
 ashley,hay,01/23/1983,13765
 evan,bert,09/11/1972,17551

Фрагмент:

int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))

выполняет три основных действия для каждой строки входного файла:

  • вычисляет время, прошедшее (в секундах )с 1970 года -01 -01 00 :00 :00 UTC (в системах POSIX ), не считая високосных секунд, сmktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00)
  • вычисляет разницу во времени между указанной выше величиной и переменной today, которая содержит количество секунд, прошедших во время выполнения с 1970 года -01 -01 00 :00 :00 UTC.
  • он делит разницу во времени в секундах на 3600 *24, чтобы получить то же самое в днях, и учитывает только целую часть результата, чтобы получить целые дни с помощью int().

Вы можете поиграть с этим, чтобы получить разницу во времени в секундах, минутах, часах в зависимости от ваших потребностей. ХТХ

2
18.03.2021, 23:01

В зависимости от того, чего вы действительно хотите:

разница в годах:

(echo "firstname,lastname,d"; cat input.csv) | csv-sqlite \
 "select *, strftime('%Y', 'now') - substr(d, 7, 4) as year_diff
  from input" | csv-header --remove

возраст:

(echo "firstname,lastname,d"; cat input.csv) | csv-sqlite
  "select *, strftime('%Y', 'now') - substr(d, 7, 4) -
             case when strftime('%m%d', 'now') >= (substr(d, 1, 2) || substr(d, 4, 2))
             then 0 else 1 end as age
  from input" | csv-header --remove

csv -sqlite и csv -заголовок взяты из csv -nix -tools

0
18.03.2021, 23:01

Теги

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