2023.12.18
STAFF BLOG
スタッフブログ
TECHNICAL
テクログ
概要
IT開発者にとって避けては通れない数ある Linux コマンドのうちから、厳選してご紹介する不定期コーナー“素敵だら! Linux コマンド”。
本コーナー突然の最終回を飾るのは awk
です。 awk
を単なるコマンドとして扱うべきかどうかは少し迷うところでもありますが、そこは最終回なので気にしません。
awk
を一言で表すと、超強力なテキスト操作コマンド、という感じでしょうか? コマンドと言いつつ、プログラミング言語でもあるので、test.awk
のようにファイルに処理内容を記載して実行することもできます。プログラミング言語でもある、というところからも、その多機能性が分かります。
細かい説明や仕様などはもっといい記事があるのでそちらを参照していただくとして、今回は利用例の紹介にとどめようと思います。ちょっと無理のある、ニッチな紹介になってるので、大体こんなことが出来るんだな、くらいで読んでください。
利用例
aws s3 コマンドで、ファイルサイズが 300kb 以上のものだけURLを取得
aws s3 ls s3://mybucket/mydir/ --profile myprofile --recursive --human-readable \
| awk -v PREFIX=https://mydomain/ '{if (int($3) > 300) print PREFIX$5}'
aws s3 の --human-readable
オプションはファイルサイズを表示できるので、それを利用して awk
では絞り込みを行った上で print
により表示を行っています。if 文を使って取得内容を絞り込めるので複雑な要望にも応えてくれます。if 文の代わりに、正規表現を使うこともできます。
if 文で $3
という変数を参照しています。awk ではデフォルトでタブや半角スペースなどのホワイトスペースで区切られた出力を箇所ごと $n
のナンバリングされた変数に格納します。$0
には1行まるごとが格納されます。
aws s3 の結果は
2021-06-16 11:19:28 30.9 KiB mydir/myfile.jpg
のようになっているので、$3
は 30.9kb
が入ります。
-v
オプションによって事前に変数も定義できるのでワンライナーながら処理の見通しもよくなりますね。
条件に合ったファイルのみ別のディレクトリにディレクトリパスを保持したままコピー
find source/ -type f -name *target* \
| awk -F'/[^/]*$' \
'{SRC=$0}{TRG="new/"$1} {system("mkdir -p "TRG" && cp -a "SRC" "TRG" ")}'
(他にもっと簡単な方法がありそうということは置いといて)
先の例では awk
内で出力内容に対して if 文を使用していましたが、ファイルの条件については find
が優秀なので、更新/作成日、サイズ、拡張子など、ある程度絞る込めると思います。
2 行目の -F
は区切り文字を指定するオプションで、正規表現によりスラッシュを含まない最後の文字列を指定しているので、$1
には対象ファイルのディレクトリパスが含まれます。
3 行目では system
を使用して、文字列をOSのコマンドとして実行します。system
から変数を使うには、分かりづらいですが "VAR"
のように変数を展開しつつ、ダブルクォーテーションを 文字列として認識させるためにエスケープしています。また SRC
, TRG
の2つの変数を、$n
変数を使って定義しています。
ちなみに、ファイル名にマルチバイトやスペースを含む場合は、ファイル名として正しく認識できないことがあるので \""VAR"\"
のように文字列展開しつつ、エスケープされたダブルクォーテーションで囲んで文字列として扱うように調整が必要です。
ここまでくると、shell スクリプト用意しておいた方がいいじゃん、ってなるんですが、普段コマンドに触れない人にはスクリプトを実行させるよりも、ワンライナーのコマンド実行させる方がハードルが低いので、そういう時には system
を使って実行しています。とりあえず print
しておいて bash
にパイプで渡して実行とかでも行けそうですが。
以上、awk
の解説でした!
awk
はプログラミング言語なのでなんでもできてしまうので、ついつい無駄に時間をかけてワンライナーを作り勝ちですが、shell スクリプトでやったほうがすぐ解決することも多いので、ご注意を!
それではまた逢う日まで!さようなら~