便利だったのでメモ。
やりたいこと
以下のように特定のバケットにあるファイルから最新のファイル名を1つ取得したい。
> aws s3 ls s3://<バケット名>/
2019-11-26 09:01:32 0 hoge1.txt
2019-11-26 09:01:54 0 hoge2.txt
2019-11-26 09:01:25 0 hoge3.txt
2019-11-26 09:01:46 0 hoge4.txt
2019-11-26 09:01:39 0 hoge5.txt
# 「hoge2.txt」がほしい
> <いい感じのコマンド>
hoge2.txt
aws s3 ls
に最終更新日時が含まれているのでできなくはなかろうと思って調べて試してみました。
いい感じのコマンド
> aws s3 ls s3://<バケット名>/ | sort -nr | head -n 1 | awk '{print $NF}'
hoge2.txt
いい感じです。
ポイント
ls
コマンドで出力される最終更新日時はPUT開始時間
下記によると最終更新日時はPUT開始時間だそうなので、ファイル作成・更新日時でも、PUT後に参照可能になった時間でもないことに注意しましょう。
S3の最終更新日時(Last Modified)の罠 - Qiita
https://qiita.com/katsuyan/items/bf6f1a06d8148212c057
sort
コマンドで並び替え
[aws]s3 lsで取得したファイルを更新日時順でソートする
https://blog.hello-world.jp.net/aws/4254/
nオプションで先頭を数値とみなしてソートすることで更新日時順にソートされます。
また、rオプションで降順にソートしています。
aws s3 ls
コマンドの結果をsort
コマンドに渡してやればよいとのことでした。
# 昇順
> aws s3 ls s3://<バケット名>/ | sort -n
2019-11-26 09:01:25 0 hoge3.txt
2019-11-26 09:01:32 0 hoge1.txt
2019-11-26 09:01:39 0 hoge5.txt
2019-11-26 09:01:46 0 hoge4.txt
2019-11-26 09:01:54 0 hoge2.txt
# 降順
> aws s3 ls s3://<バケット名>/ | sort -nr
2019-11-26 09:01:54 0 hoge2.txt
2019-11-26 09:01:46 0 hoge4.txt
2019-11-26 09:01:39 0 hoge5.txt
2019-11-26 09:01:32 0 hoge1.txt
2019-11-26 09:01:25 0 hoge3.txt
head
コマンドで1行目を取得する
ファイルの先頭から表示するheadコマンドの詳細まとめ【Linuxコマンド集】
https://eng-entrance.com/linux-command-head
head
コマンドの-n
オプションで出力する行数が指定できるので、それを利用します。
> aws s3 ls s3://<バケット名>/ | sort -nr | head -n 1
2019-11-26 09:01:54 0 hoge2.txt
awk
コマンドでファイル名を取得する
最終更新日、日時、ファイルサイズ、ファイル名と並んでいる中からファイル名のみ出力させたい場合、awk
コマンドが利用できました。
4番目にあるのでawk '{print $4}'
とも指定できますし、最後にあるのでawk '{print $NF}'
ともできます。
AWS(Amazon Web Services) - aws S3 lsコマンドでファイル名だけを表示させたい|teratail
https://teratail.com/questions/168264
awk とシェルとの値の受け渡しについて - Qiita
https://qiita.com/shotets/items/b9ebf936b4152ea12aa1
> aws s3 ls s3://<バケット名>/ | sort -nr | head -n 1 | awk '{print $NF}'
hoge2.txt
下層ディレクトリ(キー)にあるファイルもまとめてソートしたい
aws s3
コマンドの--recursive
オプションを利用すれば実現できました。
ls — AWS CLI 1.16.291 Command Reference
https://docs.aws.amazon.com/cli/latest/reference/s3/ls.html
下層にあるファイルの場合、ディレクトリ(キー)名が含まれるので、basename
コマンドでファイル名のみ取得することもできます。
【 basename 】コマンド――パス名からファイル名を取得する:Linux基本コマンドTips(177) - @IT
https://www.atmarkit.co.jp/ait/articles/1801/25/news025.html
# ファイルをfooディレクトリ(キー)下に追加
> aws s3 cp hoge6.txt s3://<バケット名>/foo/
> aws s3 ls s3://<バケット名>/ \
| sort -nr
2019-11-26 09:01:54 0 hoge2.txt
2019-11-26 09:01:46 0 hoge4.txt
2019-11-26 09:01:39 0 hoge5.txt
2019-11-26 09:01:32 0 hoge1.txt
2019-11-26 09:01:25 0 hoge3.txt
PRE foo/
> aws s3 ls --recursive s3://<バケット名>/ \
| sort -nr | head -n 1
2019-11-26 09:23:39 0 hoge/foo/hoge6.txt
2019-11-26 09:01:54 0 hoge/hoge2.txt
2019-11-26 09:01:46 0 hoge/hoge4.txt
2019-11-26 09:01:39 0 hoge/hoge5.txt
2019-11-26 09:01:32 0 hoge/hoge1.txt
2019-11-26 09:01:25 0 hoge/hoge3.txt
> aws s3 ls --recursive s3://<バケット名>/ \
| sort -nr | head -n 1 | awk '{print $NF}'
foo/hoge6.txt
> basename "$(aws s3 ls --recursive s3://<バケット名>/ \
| sort -nr | head -n 1 | awk '{print $NF}')"
hoge6.txt
fish shellな方はこちら
> basename (aws s3 ls --recursive s3://<バケット名>/ \
| sort -nr | head -n 1 | awk '{print $NF}')
hoge6.txt
Windowsな方は、、、ゴメンナサイ。WSL使ってください。
別解
本記事をまとめ終わったあとにorz、Stack Overflowでみかけた別解です。
amazon web services - get last modified object from S3 CLI - Stack Overflow
https://stackoverflow.com/questions/31062365/get-last-modified-object-from-s3-cli
aws s3api list-objects-v2
コマンドを利用して--query
オプションで絞り込みます。なるへそ。
こちらは指定せずとも再帰的にファイルを取得してくれました。
> aws s3api list-objects-v2 \
--bucket "<バケット名>" \
--query 'reverse(sort_by(Contents, &LastModified))[:1].Key' \
--output=text
hoge6.txt
参考
S3の最終更新日時(Last Modified)の罠 - Qiita
https://qiita.com/katsuyan/items/bf6f1a06d8148212c057
[aws]s3 lsで取得したファイルを更新日時順でソートする
https://blog.hello-world.jp.net/aws/4254/
ファイルの先頭から表示するheadコマンドの詳細まとめ【Linuxコマンド集】
https://eng-entrance.com/linux-command-head
AWS(Amazon Web Services) - aws S3 lsコマンドでファイル名だけを表示させたい|teratail
https://teratail.com/questions/168264
awk とシェルとの値の受け渡しについて - Qiita
https://qiita.com/shotets/items/b9ebf936b4152ea12aa1
ls — AWS CLI 1.16.291 Command Reference
https://docs.aws.amazon.com/cli/latest/reference/s3/ls.html
【 basename 】コマンド――パス名からファイル名を取得する:Linux基本コマンドTips(177) - @IT
https://www.atmarkit.co.jp/ait/articles/1801/25/news025.html
amazon web services - get last modified object from S3 CLI - Stack Overflow
https://stackoverflow.com/questions/31062365/get-last-modified-object-from-s3-cli