シェルのdateコマンド(Linux、MacOS/FreeBSD)の演算いろいろ

dateコマンドはLinux系とMacOS/FreeBSD系でパラメータが全然違うのでよく使うものをまとめ。追々追記。

dateコマンドのバージョン

MacOS
$ uname -a
Darwin MacbookM1 Darwin Kernel Version 20.3.0: Thu Jan 21 00:06:51 PST 2021; root:xnu-7195.81.3~1/RELEASE_ARM64_T8101 arm64
$ man date | tail -3
     A date command appeared in Version 1 AT&T UNIX.

BSD                               May 7, 2015                              BSD

Linux
$ uname -a
Linux XXX 4.14.94-164.ELK.el6.x86_64 #1 SMP Wed Jan 16 16:56:35 CST 2019 x86_64 x86_64 x86_64 GNU/Linux
$ date --version
date (GNU coreutils) 8.4
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 

任意日付の指定方法

MacOS
-j : 任意日付の指定ありの場合、-jオプションをつける
-f : 入力日付のフォーマット
最後の"+〜"は、出力フォーマット
$ date -jf "%Y-%m-%d" 2021-03-01 "+%Y%m%d"
20210301
フォーマットが一致しないとエラーとなる
$ date -jf "%Y-%m-%d" 2021/03/01 "+%Y%m%d"
Failed conversion of ``2021/03/01'' using format ``%Y-%m-%d''
date: illegal time format

Linux
Linux(GNU coreutils)のdateコマンドは入力日付のフォーマットを勝手に解釈してくれて便利。
"+〜"は、出力フォーマット。位置は、前でも後ろでもOK。MacOSだと最後に指定しないとエラーになる。
$ date "+%Y-%m-%d" "-d 20210301"
2021-03-01

$ date "+%Y-%m-%d" "-d 2021-03-01"
2021-03-01

$ date "+%Y-%m-%d" "-d 2021/03/01"
2021-03-01

$ date "-d 20210301" "+%Y-%m-%d"
2021-03-01

日付の演算(加算・減算)、前日・翌日の取得

MacOS
-v : 日(d)/月(m)など複数指定可能
複数指定した場合は、最初のパラメータから計算されていくので、「-v-1d -v-1m 」と「-v-1m -v-1d」では結果が異なる。
前日(−1)を取得
$ date -v-1d -jf "%Y-%m-%d" 2021-03-01 "+%Y%m%d"
20210228

1日前のさらに1か月前を取得
$ date -v-1d -v-1m -jf "%Y-%m-%d" 2021-03-01 "+%Y%m%d"
20210128

1か月前の1日前を取得
$ date -v-1m -v-1d -jf "%Y-%m-%d" 2021-03-01 "+%Y%m%d"
20210131


Linux
-d にそのまま続けて加減算の日/月を指定
減算の場合は、「1 day ago」とか「1 month ago」とか。MacOSの場合と違って順番は関係ない様子。
$ date "+%Y-%m-%d" "-d 20210301 1 month ago 1 day ago"
2021-01-31

$ date "+%Y-%m-%d" "-d 20210301 1 day ago 1 month ago"
2021-01-31


日付の計算(加減算)を行う場合、どちらが便利なのかは微妙な感じがする。MacOS/FreeBSDの方が便利そうだがバグを生む原因にもなりそう。


bashでforループ

たまにbashのコマンドラインで複数ファイルを、なんやかんやでワンライナーforループで処理させたい場合がありますが、たまにやるので ;(セミコロン)の位置を忘れたりするのでメモ。

適当にファイルを作成。
$ touch a.txt b.txt c.txt a.log
$ ll
total 0
drwxr-xr-x 1 user01 user01 4096 Jan 18 15:51 .
drwxr-xr-x 1 user01 user01 4096 Jan 18 15:50 ..
-rw-r--r-- 1 user01 user01    0 Jan 18 15:51 a.log
-rw-r--r-- 1 user01 user01    0 Jan 18 15:51 a.txt
-rw-r--r-- 1 user01 user01    0 Jan 18 15:51 b.txt
-rw-r--r-- 1 user01 user01    0 Jan 18 15:51 c.txt
$ 

で、ワンライナーのサンプル。
$ for FILE in `ls *.txt`; do echo "FILE=$FILE"; done
FILE=a.txt
FILE=b.txt
FILE=c.txt
$ 


lftpコマンドによるsftpサーバへのアクセス

以前、lftpコマンドによるFTPSサーバへのアクセスでFTPSへのアクセスを行いましたが、今回はsftpサーバへアクセスします。
sftpコマンドでもできるのですが、パスワードの扱いやもろもろでlftpコマンドでやった方が簡単だったりしたのでそのメモ。

FTPSはFTP over SSL/TLSで、中身はFTPのままです(暗号化はしてますが)。一方、SFTPはSSH File Transfer Protocolで、雰囲気的にはFTP over SSHな感じですが実際にはFTPとは全く別物です。しかし、lftpコマンドを使う場合は、そういったことを意識することなく両方のサーバにFTPライクなコマンドでアクセスできるので便利。

lftpによるsftpサーバへのアクセス
lftp -c "open -u ${USER}:${PASSWD} -p ${DEST_PORT} sftp://${DEST_HOST}; $CMD"

ちなみに、前回のftpsの例は
lftp -c "open -u ${USER},${PASSWD} -p ${FTPS_PORT} ${FTPS_HOST}; $CMD"


FTPS - Wikipedia ポート番号は990
SSH File Transfer Protocol - Wikipedia ポート番号は22


makeからシェルコマンドを実行して結果を変数に取得

久々にmakefileをさわる事があり、シェルの実行結果を取得する必要があったのでそのサンプル。
シェルでやってることは、単にファイル名を取得して実際にはそのファイルにたいして何かしらの処理をするってことだけ。ここではファイル名をechoしてるだけ。

makefile
01:
02:
03:
04:
05:
06:
07:
all:
	@echo "*** start"
	@FILES=`ls *.txt`; \
	for FILE in $$FILES; do \
	    echo "    file=$$FILE"; \
	done;
	@echo "*** end"

ファイルの一覧:
[user01@pc02 shell]$ l
合計 4
drwxrwxr-x. 2 user01 user01  78  2月 18 00:20 .
drwxrwxr-x. 3 user01 user01  18  2月 17 23:55 ..
-rw-rw-r--. 1 user01 user01   0  2月 17 23:59 aaa.txt
-rw-rw-r--. 1 user01 user01   0  2月 17 23:59 bbb.txt
-rw-rw-r--. 1 user01 user01   0  2月 17 23:59 ccc.log
-rw-rw-r--. 1 user01 user01 128  2月 18 00:20 makefile
-rw-rw-r--. 1 user01 user01   0  2月 17 23:59 test.txt

実行結果:
[user01@pc02 shell]$ make
*** start
    file=aaa.txt
    file=bbb.txt
    file=test.txt
*** end

コマンドの前にある@はmake自体のechoを抑制するもの。付けない場合の実行結果は下記の通り。
[user01@pc02 shell]$ make
echo "*** start"
*** start
FILES=`ls *.txt`; \
for FILE in $FILES; do \
    echo "    file=$FILE"; \
done;
    file=aaa.txt
    file=bbb.txt
    file=test.txt
echo "*** end"
*** end


lftpコマンドによるFTPSサーバへのアクセス

lftpコマンドによるFTPSサーバへのアクセス Linuxのlftpコマンドでアクセスするだけ。
引数なしてlftpを実行するとシェルっぽい対話形式での接続が可能になります。
-c の引数で直接lftpコマンドを渡すことができ、
-f でlftpコマンドを列挙したファイルを指定して実行できます。
ファイル指定の場合、-f script-file arg1 arg2...のように引数を続けるとファイル内で@1,@2等で展開して使うことができます。

lftp.sh
01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
#!/bin/bash

USER=lftp_user
PASSWD=lftp_passwd
FTPS_HOST=ftps01.com
FTPS_PORT=990
SRC_DIR=$HOME
DST_DIR=/tmp
FILE=$1

function cmd_lftp () {
    CMD="$1"
    debuglog "lftp cmd=[$CMD]"
    lftp -c "open -u ${USER},${PASSWD} -p ${FTPS_PORT} ${FTPS_HOST}; $CMD"
}


RC=`cmd_lftp "ls ${DST_DIR}/${FILE}"`
LFTP_RC=$?
if [ $LFTP_RC -ne 0 ]; then
    echo "lftp cmd error. rc=$LFTP_RC"
    exit 1
fi

if [ "$RC" = "" ]; then
    CNT=0
else
    CNT=`echo $RC | wc -l`
fi

if [ $CNT -gt 0 ]; then
    echo "${DST_DIR}/${FILE} exist."
    exit 0
fi

# send file
RC=`cmd_lftp "debug 3; mput -O ${DST_DIR}/ ${SRC_DIR}/${FILE}"`
LFTP_RC=$?
if [ $LFTP_RC -ne 0 ]; then
    echo "lftp cmd error. rc=$LFTP_RC"
    exit 1
fi
やってることはいたって単純で、lftp.sh <送信対象ファイル> として実行すると存在しない場合のみ送信する、ということをやっています。

lftpでコマンドを渡すときは、通常のシェルのようにセミコロン(;)で区切ります。
37行目のdebug 3は、接続時の情報や転送状況などデバッグするのに役立ちます。

ちなみに、ポートの21と990の使い分けは特に決めがあるわけではなく、通常のFTPとFTPSと共存させたい時FTPを21でFTPSを990としているようです。また、FTPSをFTPとしても使いたい時はFTPSを21で立てるようです。


カテゴリ

Amazon

アクセスランキング

[ジャンルランキング]
コンピュータ
261位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
47位
アクセスランキングを見る>>

RSSリンクの表示

ブロとも申請フォーム

Copyright © nopgm