TL;DR
$ ls *.zip | { while read zip_name; do md5sum $zip_name > $zip_name.md5; done; }
やりたいこと
hoge.zip
のmd5sumをhoge.zip.md5
として保存したい。
fuga.zip
、piyo.zip
も同様に処理したい。
$ ls
hoge.zip fuga.zip piyo.zip
試したけど駄目だった方法
$ ls *.zip | xargs -I{} md5sum {} > {}.md5
これをすると{}.md5
が保存されてしまう。
xargs
はリダイレクト先の文字列を置き換えられないようだ。
変数を経由する
標準入力をリダイレクト先にまで反映させたい、というだけなので、素朴に変数を使う。
bashでパイプ(標準入力)から受け付けた内容を変数に代入する
この記事でread
とcat
を使う方法が載っていた。
$ #readを使う場合
$ #標準入力が変数zip_nameに書き込まれる。ただし標準入力が複数あった場合、最初の1つのみ
$ ls *.zip | { read zip_name; md5sum $zip_name > $zip_name.md5; }
$ #catを使う場合
$ #標準入力が変数zip_nameに書き込まれる。標準入力が複数あった場合、配列として読み込まれるため失敗する。
$ ls *.zip | { zip_name=$(cat); md5sum $zip_name > $zip_name.md5; }
複数ファイルに対応する
いずれの場合も複数ファイルには対応できないので改良が必要になる。
「while read zip_name; do ~ done;
かな……長すぎて嫌だな」としばらく悩んでいたが、何のことはなくxargs
を一度挟めば良いだけだった。
$ #xargsで1つずつreadに送る
$ ls *.zip | xargs echo | { read zip_name; md5sum $zip_name > $zip_name.md5; }
さらにxargs
は引数を省略するとデフォルトでechoを実行するので、
$ #xargsで1つずつreadに送る(改)
$ ls *.zip | xargs | { read zip_name; md5sum $zip_name > $zip_name.md5; }
これで完成。
23/04/19 指摘を受け記述を削除
コメント欄で動作しないとの指摘を受け確認したところ、確かに動作しなかった。
@ko1nksm さん、ありがとうございます!
$ ls
dummy2.zip dummy.zip
$ ls *.zip | xargs | { read zip_name; md5sum $zip_name > $zip_name.md5; }
-bash: $zip_name.md5: ambiguous redirect
誤った情報を記載してしまったことを深くお詫び申し上げます。
取り急ぎ上記内容を打ち消し線で示しつつ、最終的な解決方法は週末にデバッグすることとする。
先行記事
xargs リダイレクト
で検索すると複数の記事がヒットする。
xargs は個別ファイルへ書き出すリダイレクトのパイプが使えない → for を使う
forを使う方法。
xargsで個別ファイルにリダイレクト
関数化する方法。
xargsで個別のファイルにリダイレクトしたい
shのサブシェルを呼ぶ方法。
本記事のタイトルも先行記事に倣った。
どれを使っても基本的には問題なさそう。
参考
bashでパイプ(標準入力)から受け付けた内容を変数に代入する
xargs は個別ファイルへ書き出すリダイレクトのパイプが使えない → for を使う
xargsで個別ファイルにリダイレクト
xargsで個別のファイルにリダイレクトしたい
xargsを使う際にはecho
は書かなくてもよいことをmanページから知った