Twitterでそういった処理について見かけたので、やってみた内容を備忘として残しておく。

sedでやる場合

GNU拡張されたsedの場合 -i で上書きができるので、ただ文字列を挿入するだけであれば以下のようにしてやればいい。

sed -i '1iString' *.txt
[root@BS-PUB-CENT7-01 test_dir]# cat a.txt
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20
[root@BS-PUB-CENT7-01 test_dir]# cat b.txt
b01 b02
b03 b04
b05 b06
b07 b08
b09 b10
b11 b12
b13 b14
b15 b16
b17 b18
b19 b20
[root@BS-PUB-CENT7-01 test_dir]#
[root@BS-PUB-CENT7-01 test_dir]# sed -i '1iString' {a,b}.txt
[root@BS-PUB-CENT7-01 test_dir]#
[root@BS-PUB-CENT7-01 test_dir]# cat a.txt
String
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20
[root@BS-PUB-CENT7-01 test_dir]# cat b.txt
String
b01 b02
b03 b04
b05 b06
b07 b08
b09 b10
b11 b12
b13 b14
b15 b16
b17 b18
b19 b20

ただ、これがファイルを読み込むという内容になると一手間必要になる。 一応、sedでは'r FILEPATH'で指定したファイルを読み込むことができるのだけど、これだと指定した行の後ろ(add)への差し込みになってしまう。

[root@BS-PUB-CENT7-01 test_dir]# cat add.txt
Oh,yeah!
xxxxxxx
yyyyyyy
[root@BS-PUB-CENT7-01 test_dir]# cat a.txt
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20
[root@BS-PUB-CENT7-01 test_dir]#
[root@BS-PUB-CENT7-01 test_dir]# sed '1r add.txt' a.txt
a01 a02
Oh,yeah!
xxxxxxx
yyyyyyy
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20

といっても、sedでは改行を含んだ状態では処理できないようなので、コマンド置換でただ記述してもうまく動かない。 じゃあどうするのかというと、一度改行を「\n」で表現するように置換してやればいい。insertだと余計な改行が挟まれる場合が多いため、sで行頭を置換することで対処する。

sed -i '1s/^/'$(sed -z 's/\n/\\n/g' FILEPATH)'/g' *.txt
[root@BS-PUB-CENT7-01 test_dir]# sed '1s/^/'$(sed -z 's/\n/\\n/g' add.txt)'/g' a.txt
Oh,yeah!
xxxxxxx
yyyyyyy
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20
[root@BS-PUB-CENT7-01 test_dir]# sed -i '1s/^/'$(sed -z 's/\n/\\n/g' add.txt)'/g' {a,b}.txt
[root@BS-PUB-CENT7-01 test_dir]#
[root@BS-PUB-CENT7-01 test_dir]# cat a.txt
Oh,yeah!
xxxxxxx
yyyyyyy
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20
[root@BS-PUB-CENT7-01 test_dir]# cat b.txt
Oh,yeah!
xxxxxxx
yyyyyyy
b01 b02
b03 b04
b05 b06
b07 b08
b09 b10
b11 b12
b13 b14
b15 b16
b17 b18
b19 b20

catでやる場合

対象が1ファイルであれば、そもそもcatで普通に書いてやれば標準出力で結合させることができる。

cat head.txt file.txt
[root@BS-PUB-CENT7-01 test_dir]# cat add.txt
Oh,yeah!
xxxxxxx
yyyyyyy
[root@BS-PUB-CENT7-01 test_dir]# cat a.txt
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20
[root@BS-PUB-CENT7-01 test_dir]#
[root@BS-PUB-CENT7-01 test_dir]# cat add.txt a.txt
Oh,yeah!
xxxxxxx
yyyyyyy
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20

ファイルに上書きする場合、ただリダイレクトしたりteeを使って書き込みをすると、先にリダイレクト処理が走ってしまいファイルが空になってしまう。 このため、一時ファイルを使わないのであればプロセス置換を使うか、もしmoreutilsが入っていればspongeを使うといいだろう(前にもこの辺で書いたけど)。

cat head.txt file.txt > >(sleep 0.1;cat > file.txt) #プロセス置換を使う場合
cat head.txt file.txt | sponge file.txt
[root@BS-PUB-CENT7-01 test_dir]# cat a.txt
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20
[root@BS-PUB-CENT7-01 test_dir]# cat add.txt a.txt
Oh,yeah!
xxxxxxx
yyyyyyy
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20
[root@BS-PUB-CENT7-01 test_dir]#
[root@BS-PUB-CENT7-01 test_dir]# cat add.txt a.txt > >(sleep 0.1;cat > a.txt)
[root@BS-PUB-CENT7-01 test_dir]# cat a.txt
Oh,yeah!
xxxxxxx
yyyyyyy
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20
[root@BS-PUB-CENT7-01 test_dir]#
[root@BS-PUB-CENT7-01 test_dir]# cat add.txt a.txt | sponge a.txt
[root@BS-PUB-CENT7-01 test_dir]# cat a.txt
Oh,yeah!
xxxxxxx
yyyyyyy
Oh,yeah!
xxxxxxx
yyyyyyy
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20

これを複数ファイルに対して処理するなら、xargsを使ってやればいいだけだ。

ls -1 *.txt | xargs -I@ bash -c 'cat head.txt @ > >(sleep 0.1;cat > @)'
[root@BS-PUB-CENT7-01 test_dir]# cat a.txt
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20
[root@BS-PUB-CENT7-01 test_dir]# cat b.txt
b01 b02
b03 b04
b05 b06
b07 b08
b09 b10
b11 b12
b13 b14
b15 b16
b17 b18
b19 b20
[root@BS-PUB-CENT7-01 test_dir]#
[root@BS-PUB-CENT7-01 test_dir]# ls -1 {a,b}.txt | xargs -I@ bash -c 'cat add.txt @ > >(sleep 0.1;cat > @)'
[root@BS-PUB-CENT7-01 test_dir]# cat a.txt
Oh,yeah!
xxxxxxx
yyyyyyy
a01 a02
a03 a04
a05 a06
a07 a08
a09 a10
a11 a12
a13 a14
a15 a16
a17 a18
a19 a20
[root@BS-PUB-CENT7-01 test_dir]# cat b.txt
Oh,yeah!
xxxxxxx
yyyyyyy
b01 b02
b03 b04
b05 b06
b07 b08
b09 b10
b11 b12
b13 b14
b15 b16
b17 b18
b19 b20