S3 對象批量重命名快捷方法
本文所述操作適用于兼容 S3 協議的所有存儲框架,包括 AWS S3、Aliyun OSS、MinIO、Ceph 等。
不知為何,截止目前,S3 協議并不包含對象重命名的接口。如果有重命名對象的需求,一般能想到的就是重新上傳改名之后的對象,然后從存儲桶中將原名對象刪除。很明顯,這種方式好比大炮打蚊子,目的達到了,累得一身汗,要是本地沒有備份,還得先下載,費時費力費錢。特別是當待處理的對象的數量相當龐大的時候,如果不想持續加班一個月,那就要琢磨琢磨另辟蹊徑才行。
能不能將存儲桶掛載到本地,然后用本地 shell 命令操作其中的對象呢?值得一試!
掛載
使用 rclone、s3fs-fuse、goofys 等工具掛載,這里以 goofys 為例。
- 直接下載編譯好的執行文件
wget https://github.com/kahing/goofys/releases/latest/download/goofys - 設置執行權限
chmod +x goofys - S3 密鑰配置
mkdir ~/.aws
vi ~/.aws/credentials
# 以下是 ~/.aws/credentials 內容
[default]
aws_access_key_id = xxxxxxx
aws_secret_access_key = yyyyyyyy
- 創建掛載點
mkdir /mnt/foo - 掛載
mkdir /opt/goofys
./goofys --endpoint https://us-east.s3.aws.com bucketName /mnt/foo/
- 驗證是否掛載成功。
# 列出前 10 個文件
ls /mnt/foo/ | head -n 10
# 注意:該語句并不能減少 ls 的執行時間。當文件數量過多時,可以使用通配符減少 ls 的羅列數量。
重命名
掛載成功之后,我們就可以采用 mv 或 rename 指令嘗試重命名文件了,下面以 perl 版本的 rename 為例(該版本支持正則表達式)。
# 所有文件名只保留后 5 個字符,并更改擴展名
rename 's/\w*?(\w{5})\.mdi/$1.obj/' *
# 實際也是逐個文件處理,而非一次性同時處理,文件多則耗時
# 如果文件太多則會報 "Argument list too long"(雖然參數只有一個星號,但實則是將所有文件名查找出來后執行),可以改成如下方式:
find . -name "*" | xargs rename 's/\w*?(\w{5})\.mdi/$1.obj/'
# 雖然不會報錯,但其實只是將查找文件名環節轉給了 find,總耗時是一樣的
為了更好更靈活地重命名巨量文件,只能編寫腳本了。以下是示例代碼:
rename_s3_objects()
{
local renamedCnt=0
for obj in ./*
do
if [ `expr ${#obj} - 2` -gt 8 ]; then # 如果不作判斷,那么不管文件名是否符合,正則都會執行(耗時),然后再根據執行結果看是否重命名(重命名比正則更耗時)
rename 's/\w*?(\w{5})\.mdi/$1.obj/' $obj
fi
renamedCnt=$(($renamedCnt + 1))
if [ `expr $renamedCnt % 100` -eq 0 ]; then
# 每處理完 100 個對象就輸出提示
echo "$renamedCnt objects renamed"
fi
done
return 0
}
rename_s3_objects
# 似乎 ``; $[]; $(()) 都可以執行運算
保存后,在命令行中使用 sh saved_file_name 執行即可。
經測算,在普通網絡環境下,每重命名 100 個對象(大約 100M),耗時 70s 左右。并未檢查過程中是否涉及到對象的傳輸(博主試驗的服務器并沒有帶寬使用統計),推測應該是沒有,有興趣的朋友可以驗證下。
除重命名外,類似于[批量]刪除、S3 中對象加斜杠前綴(創建文件夾并移動文件)等指令應該也可以通過掛載方式玩轉。

浙公網安備 33010602011771號