bashとlinuxを学び始めて、困った時の対応・忘れそうな使い方のメモ。
索引
- 使い方メモ
- コマンド置換
- 時間の書式
- ディレクトリ内のファイル数
- ファイル名やディレクトリ名の一部から検索する
- 行数のカウント
- 最終行の改行を削除
- 選択したテキストをファイルに挿入
- 特定のコマンドを調べる
- sedの後方参照は10個以上できない(はず)
- csv関係
- エラー対応
- /bin/bash^M: 誤ったインタプリタです: そのようなファイルやディレクトリはありません
使い方メモ
コマンド置換
-
` `(バッククォート)
や$()
で囲った内容はコマンドとして認識される。 - 基本的には
$()
を使うことが推奨される。 - 入れ子にできるため。
【参考記事】
bash Tips - コマンド置換と算術式展開、パラメータ展開
時間の書式
- 特定の日付・時間の形で出力したいとき。
- dateコマンドで使う。
例えば、「yyyyMMddHHmmss」(20201025131540)のような形式にしたい場合は
date "+%Y%m%d%H%M%S"
【参考記事】
date コマンド
ディレクトリ内のファイル数
- ディレクトリにファイルがいくつ存在しているかを調べる。
ls -1U | wc -l
【参考記事】
【linux】あるディレクトリの下にいくつファイルがあるか調べる
ファイル名やディレクトリ名の一部から検索する
- findコマンドで部分的なテキストから該当するファイルやディレクトリを検索する。
例えば、workディレクトリの「.csv」を含むファイルを検索したいときは
find work -name \*.csv
【参考記事】
ファイルなどを検索する!findコマンドの詳細まとめ【Linuxコマンド集】
findで見つけたファイルを別のディレクトリに移動させる
- findコマンドでファイルを見つけた後に、別のディレクトリに移動させたい。
- xargsを用いる。
find -name pf_diff_\*.csv | xargs -I% mv % other_dir
- xragsの
-I
オプションはその後の文字を前のコマンドの結果を格納した変数のように扱うことができるようになる。 - そのため、
%
にはfind -name pf_diff_\*.csv
の結果が入っている。
【参考記事】
find で検索したファイルを一括で移動(mv)させる
行数のカウント
-
wc -l
だと厳密には行数ではなく改行の数になる。 - そのため、最終行に改行が含まれていないと、1少ない数になってしまう。
grep -c '' sample.txt
【参考記事】
wc コマンド(grepで行数をカウントするには)
ファイルの行数を数えるのは「wc -l file」ではありません
wc -lでは文末に改行がないファイルの行数を正しく数えられない
最終行の改行を削除
- ファイルによっては自分で入れたはずはないのに、勝手に最終行に改行が入っていることがある。
- 少なくとも私の場合は、これが後の処理の邪魔で削除しなければならなかった。
例えば、下記のようなcsvファイル
"name","price","classification"
"pasta","250","carbohydrate"
"cabbage","150","vegetables"
"butter","120","fat"
←この行が改行のみで、スペースも文字もない状態
"butter","120","fat"
の下の1行が勝手に改行になっている。
これを消すために下記のような処理を加える。
cat test.csv | head -c -1
cat
の部分は特に気にしなくてもよいが、重要なのは|
の後のhead -c -1
。
末尾の1文字以外を表示する処理なので、結果的に最終行の改行は無視されている。
選択したテキストをファイルに挿入
- すでに存在しているファイルに、何らかのテキストを挿入する。
- 今回はcsvファイル(test.csv)の1行目(カラム)を別のcsvファイル(new.csv)の先頭に挿入する。
sedを用いる場合
sed -i "1 i $(head -n 1 test.csv)" new.csv
もしくは
readと変数を用いる場合
head -n 1 test.csv | { read v ;sed -i "1 i $v" new.csv; }
-
sed -i "1 i ○○"
の" "
はシングルクォーテーションでも問題ないが、変数を展開するときは" "
を使うこと。 - sedの-iオプションはファイルを編集して上書きするためのもの。
- これが抜けてると出力はされるが、ファイルは上書きされていない。
- sedのiコマンド(
"1 i ○○"
のところのi
)は対象の「前」にテキストを挿入する。
【参考記事】
sedコマンドでファイルの先頭行に文字列を挿入する
Linux:sedコマンドで上書き(インプレース)編集する方法
sed aコマンド、 iコマンドの動作(指定文字列の挿入、追加) 【Linuxコマンド】
bashでパイプ(標準入力)から受け付けた内容を変数に代入する
特定のコマンドを調べる
履歴
- 過去のコマンドを調べるのには
history
を用いるが、特定のコマンドの履歴のみ表示したいときはgrepを用いる
例えば、lsコマンドの履歴を表示したいときは
history | grep ls
プロセス
- プロセスの確認には
ps
やps aux
を用いるが、特定のコマンドや文字列についてはこちらもgrepを用いる。
例えば、inotifywaitについてだけ表示したいとき
ps aux | grep inotifywait
inotifywaitをバックグラウンドで動作させたときに、消し方が分からずにたどり着いたのがこの方法です。
sedの後方参照は10個以上できない(はず)
- 業務でカラムが10個以上あるcsvファイルを扱うことがあったとき、後方参照(
/1
や/2
)が10以降は正しく認識されなくて困った。
自分なりに考えたやり方が以下になります。
cat sample.csv | cut -d ',' -f 10-11 | sed -e "s/\(.*\),\(.*\)/\1,\2/g"
-
cut -d ',' -f 10-11
で,
区切りの10~11番目のテキストを切り出し -
sed -e "s/\(.*\),\(.*\)/\1,\2/g"
で後方参照している -
cut
で切り出したのは10番目と11番目の2つだけなので、後方参照も\10と\11とはならず、\1と\2のように小さい数に抑えられる。
【参考記事】
bioinformatics(sed)
csv関係
業務でcsvをこれでもかと扱っていたのでcsvに関することはこちらでまとめています。
特定の文字列が何行目にあるか(csvのカラムの場所探し)
- これまた業務で扱ったcsvの話で、カラムの数が軽く200を超えており、その中から20個ほどを抽出して別のファイルを作成する必要があった。
- 考えたのは、カンマで区切りで改行⇒該当のカラムが何行目にあるか という方法。
$ cat sample.csv
1番目のカラム,2番目のカラム,3番目のカラム,4番目のカラム,5番目のカラム
a,b,c,d,e
$ head -n 1 sample.csv | sed -e "s/,/,\n/g" | grep -e "3番目のカラム" -n
3:3番目のカラム,
このように、探したいカラムが何番目にあるかが検索できます。
【参考記事】
Linuxのgrep(指定文字検索)で該当行の行番号のみ出力する
特定の列を取り出す
- 例えば、カンマ区切りの1番目のフィールドを取り出す場合
cut -d ',' -f 1 sample.csv
【参考記事】
CSV ファイルの特定の列を取り出す
カラム数の確認
cat sample.csv | awk -F ',' '{print NF}'
【参考記事】
awkを使ってCSVのカラム数をチェック
特定のフィールドにテキストを挿入
- 例えば、30番目のフィールドが空で、そこにテキストを入れたい場合
- なおかつ、csvの最終行が対象としてます。
tail -n -1 sample.csv | awk -F, 'BEGIN{OFS=","}{$30="abcde";print}' > sample2.csv
【参考記事】
awkでcsvに任意の列を追加する
※注意点
上の参考記事にも書かれていますが、"abc,def"
のように、1個のカラムの中にカンマが含まれているとうまく動作しません。
エラー対応
/bin/bash^M: 誤ったインタプリタです: そのようなファイルやディレクトリはありません
- 複数人で開発をしていて、gitから引っ張ってきたシェルを実行するとこの表示がでることがよくあった。
$ ./test.sh
-bash: ./test.sh: /bin/bash^M: 誤ったインタプリタです: そのようなファイルやディレクトリはありません
なので、参考記事と同じことを実行
sed -i 's/\r//' test.sh
【参考記事】
/bin/bash^M: bad interpreter: そのようなファイルやディレクトリはありません (No such file or directory)
最後に
この記事に載せたのが最適解であるのかはわかりません。
調べればもっと楽なやり方もあるのかもしれません。