Help us understand the problem. What is going on with this article?

AWS CLIでAmazon S3のバケットにあるファイルから最新のファイル名を1つ取得する

便利だったのでメモ。

やりたいこと

以下のように特定のバケットにあるファイルから最新のファイル名を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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away