1. tsuyoshi_cho

    誤字っぽいので

    tsuyoshi_cho
Changes in body
Source | HTML | Preview

シェルだけで、ファイル名だけ変更、またはファイルを一括指定

ファイルパス展開で{a,b,c}記法を使うと、パスの一部(例:ファイル名)だけが違う複数ファイルを簡単に指定できます。

mv /the/long/long/path/to/file /the/long/long/path/to/new_file

これが

mv /the/long/long/path/to/{file,new_file}

と簡単にできます。zshなら補完も可能です。
ファイル以外でも下記のようにテキストを展開することができます。

$ echo hoge{fuga,piyo,muga}
hogefuga hogepiyo hogemuga

シェルだけで、連番のファイルをまとめて選択

ファイルパス展開で[012]記法を使うと、連番のファイルを選択することができます。

cat /blah1 /blah2 /blah3 /blah4

これが

cat /blah[1234]

と簡単にできます。
(存在しないファイルはスキップされます。)

シェルだけで、落ちても自動で再起動

while true; do target_script; sleep 1; done

終了する際はCtrl-Cを連打してください。

シェルだけで、forループのワンライナー

(これは基本かもしれませんが、なんだかんだで重宝します・・)

for i in {1..100}; do target_script $i; done

(sedだけど)シェルだけで一括置換

sed -iを使うと、ファイルの中身を直接書き換えることができます。
例えば、dictionaryをdictonaryとtypoしてしまったケースがたくさんあるとすると、下記のコマンドで置換できます。(必ずgit等で前の状態に戻せるようにしておいてください!)

sed -i '' -E 's/(d|D)ictonary/\1ictionary/g' **/*.[mh]

-i ''は、置換結果を元のファイルに書き出すオプションです。-i '.new'とすれば、入力ファイル.newのように、.newが末尾についたファイル名で保存されます(=上書きされません)。
-Eは高度な正規表現を有効にするためのオプションです。

ファイル数が多い場合はagで絞ってから置換してもよいでしょう。

sed -i '' 's/some_bad_method_name_or_something/good_one/g' `ag -l some_bad_method_name_or_something ./lib`

※ag/ackがない場合はgrep -Rで代用できますが、.gitが置換対象に含まれないよう注意してください

シェルだけで、並列実行

http://stackoverflow.com/questions/5547787/running-shell-script-in-parallel

gnu parallelコマンドを使うか、bashに内蔵されたバックグラウンド実行機能(&やbgコマンドを使うもの)+プロセスの終了待ちをするwaitコマンドを使えば簡単に並列実行できます。

parallel篇

cat url_list.txt | parallel wget

parallelコマンドは入力を改行で区切り、指定されたコマンドの後ろに付けて実行します。並列実行数はデフォルトでCPUコア数(スレッド数?)と同じですが、--jobsで指定もできます。

bashだけ篇

下記のコードはstackoverflowの引用です。 (Quoted from stackoverflow.)

#!/bin/bash
for i in {1 1000}
do
   ( Generating random numbers here , sorting  and outputting to file$i.txt ) &
   if (( $i % 10 == 0 )); then wait; fi # Limit to 10 concurrent subshells.
done
wait

さすがに最大ジョブ数で管理することはできず、10個立ち上げたら全部終わるのをまってから、また10個立ち上げて・・という流れになります。

(おまけ的な)シェルだけで、後置ならぬ前置if文や三項演算子っぽい何か

some_command && echo success!
some_command || echo fail...
some_command && echo success! || echo fail...
let cnt=0;

while ...; do
    some_processing;
    let cnt++;
    (( $cnt >= 10 )) && break;
done 

(おまけ2)xargsでシェルスクリプトを渡す

bash -cを使えばシェルスクリプトの文字列を直接実行でき、これとxargsを組み合わせればechoの中でバッククォート展開を叩いたりできます。
xargs -iで{}がファイルパスに置き換わる(Mac OS X(おそらくBSDも)はxargs -I'{}'と明示的な指定が必要)ます。

下記は「HogeClass」という文字が含まれているファイルが最後にcommitされた日を表示する例です。

ag -l 'HogeClass' | xargs -n1 -i bash -c 'echo "{}: `git log -n 1 --pretty=format:%cd -- {}`"'

※シェル芸というワードはこちらのtwitterアカウント名から頂きました