📟

Linux Shellでよく使うコマンド集

2021/02/23に公開約7,000字

shellを書いたりターミナルへ直接コマンド打ったりするとき、ちょくちょく調べるのが面倒なのでまとめ

shファイルのテンプレート

文字コードはUTF-8, 改行コードはLF

test.sh
#!/bin/sh

set -eu
set -x	# コマンドをすべて出力
#trap read debug	# 一行ずつ実行

#--------------------------------
# shの説明
#--------------------------------

cd `dirname $0`

# ここに色々処理を書く

echo "finish..."

それぞれの説明

どのプログラムで動かすかの宣言

単なるコメントではないです。
「binディレクトリ配下にあるshでこのファイルを動かします」の宣言、みたいな

#!/bin/sh

これを書いておくとsh xxx.shではなく(実行権限をつけた上で)./xxx.shでも実行できるようになる

エラー発生時にshellの実行を止める

デフォルトではエラーが発生しても止まらない

set -e

止めたくないときはset +eを実行

未定義の変数を使おうとしたときshellの実行を止める

set -u

file_path="xxx/xxx/xxx.txt"

rm ${fale_path}	# スペルミスで違う変数名扱いになる

shell実行時にコマンドをすべて出力する

Windowsのコマンドプロンプトの @echo on みたいな

set -x
# 以降はコマンドが出力される

出力をやめるとき

set +x

shellを1行ずつ実行する

set -x
trap read debug

# 以降は一行ずつ実行

shファイルがあるディレクトリに移動

Windowsのコマンドプロンプトの cd %~dp0 みたいな

cd `dirname $0`

$0 には現在実行中のshファイルへのパスがセットされている

shellの実行を一時停止する

  • [Enter]以外では進まない
  • メッセージは出ずに実行だけ止まるので、直前でechoするといい
echo "続けるにはEnterを入力してください"
read Wait

ファイルを一覧表示

Windowsのコマンドプロンプトの dir みたいな

# 今いるディレクトリのファイル一覧を出力
ls

# もっと詳しく情報を出力(llと同等)
ls -l

# 指定ディレクトリを指定しての一覧表示もできる
ls xxx/xxx/

if文

if <条件式> ; then
	# 条件式がtrueのとき実行
elif <条件式> ; then
	# 条件式がtrueのとき実行
else
	# どちらもfalseのとき実行
fi

等しいか判定

[ の前後にはスペースを入れないとエラー

# valが数値のとき
if [ 1 -eq $val ] ; then
...(省略)

# valが文字列のとき
if [ "aaa" = $val ] ; then

等しくないことを判定

# valが数値のとき
if [ 0 -ne $val ] ; then
...(省略)

# valが文字列のとき
if [ "aaa" != $val ] ; then

shell実行時引数をチェック

引数が1つ必要な場合

test.sh
# $# 引数の個数
# $0 実行したshファイルへのパス
if [ $# != 1 ]; then
	echo "ex. sh $0 ファイル名"
	# => ex. sh test.sh ファイル名 と出力
	exit 1
fi

ファイルの存在有無を確認

1ファイルだけ探す

if [ -e ${file_path} ]; then
	echo "ファイル${file_path}がありました"
fi

if [ ! -e ${file_path} ]; then
	echo "ファイル${file_path}がありません"
fi

ディレクトリの存在有無を確認

if [ -d ${dir_path} ]; then
	echo "ディレクトリ${dir_path}がありました"
fi

if [ ! -d ${dir_path} ]; then
	echo "ディレクトリ${dir_path}がありません"
fi

正規表現にマッチするか

# 「A012」とかでマッチする
if [ `echo ${str} | grep "[A-Z][0-5]+"` ]; then
	echo $str
fi

if [ ! `echo ${str} | grep "[A-Z][0-5]+"` ]; then
	# マッチしないとき入る
	echo $str
fi

whileループ

while <条件式>; do
	# 条件式がtrueの間ループ
done

無限ループ(止めるときは [Ctrl] + C)

while true; do
	echo "1秒待ってループ"
	sleep 1
done

コピー

ファイルのコピー

cp ${src_path} ${dest_path}

オプションの一覧

オプション 意味
-r (コピー元がディレクトリのとき)ディレクトリの配下をすべてコピー
-v コピー結果を出力(どのファイルをコピーしたか)
-f コピー先に同名ファイルがあるとき上書きする
-a サブディレクトリも含めて属性とかを可能な限り保持してコピー
cp -r ${src_path} ${dest_path}

移動

ファイルを移動

mv ${src_path} ${dest_path}

オプションの一覧

オプション 意味
-v 移動結果を出力(どのファイルを移動したか)
-f 移動先に同名ファイルがあるとき上書きする

まとめて移動もできる

# xxx1.txt,xxx2.txtをabc/test_dir/ディレクトリへ移動
mv xxx1.txt xxx2.txt abc/test_dir/

ファイルの削除

rm ${file_path}

オプションの一覧

オプション 意味
-r ディレクトリを削除(サブディレクトリ含めて)
-f 引数が存在しないファイルのとき、何もしない(すでに削除済みのときエラーにしない)
# ディレクトリの場合
rm -r ${dir_path}

ファイルを検索

存在しないときはエラー

find <検索対象ディレクトリ> -name <検索するファイル名>

圧縮・解凍する

zipのコマンドがある場合

# 圧縮
zip xxx.zip <ファイルやディレクトリ>

# 解凍
unzip xxx.zip

アーカイブ=複数ファイルを1ファイルに固める(無圧縮)

tar -cf xxx.tar <ファイルやディレクトリ>

# 実行時にアーカイブしたファイルを出力する(vを追加)
tar -cvf xxx.tar <ファイルやディレクトリ>

# 展開
tar -xvf xxx.tar

# 展開先を指定
tar -xvf xxx.tar -C <展開先のディレクトリ>

圧縮する(実際はアーカイブ化→圧縮を順に行っている)

tar -jcf xxx.tar.bz2 <ファイルやディレクトリ>

# 実行時に圧縮したファイルを出力する(vを追加)
tar -jcvf xxx.tar.bz2 <ファイルやディレクトリ>

# 解凍
tar -jxvf xxx.tar.bz2

エスケープする

基本的にダブルクォート("aaa")を使えばOK

記号一覧

名前 記号 入力方法 動作
ダブルクォート " Shift + 2 $、バッククォート、バックスラッシュ以外をエスケープ
シングルクォート ' Shift + 7 全部エスケープ
バックスラッシュ \ \(円マーク) 1文字だけエスケープ
バッククォート ` Shift + @ コマンドとして実行する。※エスケープ文字ではない
str = "abc"

# ダブルクォート
echo "${str}"
# => abc

# シングルクォート
echo '${str}'
# => ${str}

ファイル名に)とかが使われているとき、コマンドでうまく実行できないためエスケープする必要がある

# xxx(1).txtに対して実行
#cp -v xxx(1).txt ${dest_path}	# NG
cp -v xxx\(1\).txt ${dest_path}	# OK

コマンドの実行結果を変数に入れる

コマンドを ` (バッククォート)で囲む

# xxx.txtがあるディレクトリ名を取得
dir_name=`dirname */xxx.txt`
echo $dir_name

ディレクトリ内のファイル数をカウントする

ls -1 | wc -l

テキストファイルの操作

ファイルの中身を出力

全部出力

# ファイルの中身が一行だけで改行なしの場合、改行が出力されないので注意
cat ${file_path}

最後の数行だけ出力(ログファイルとかに使う)

tail ${file_path}

ファイルが更新されたら出力し続ける(止めるには [Ctrl] + C)

tail -f ${file_path}

(複数ファイルがあるとき)最後に更新されたファイルの中身を見る

# 取得したいファイルがあるフォルダへ移動してから実行
ls -t | head -n 1 | xargs tail -f

バイナリで出力

# 2バイト単位、16進数で出力
od -h ${file_path}
# -> 0000000     1d01 の形式

viで編集する

vi ${file_path}

操作方法

  • [ESC]でコマンドモードになる
  • 終了
    • :q:保存せずに終了
    • :wq:上書き保存して終了(書き込み可能状態でないとエラー)
  • 編集する
    • :i:編集モードに変更
    • x:1文字削除

テキストファイルの中身を検索する

if grep -q 'str' ${file_path}; then
	echo strがあります
fi

# 正規表現
if grep -E '^str$' ${file_path}; then
	echo strのみの行があります
fi

テキストファイルの中身を書き換える

一致する文字列を置換する

# 置換後のファイルを別名保存
sed -e 's/置換対象の文字列/置換後の文字列/g' test.txt > test_new.txt

# 置換後のファイルを上書き保存
sed -i -e 's/置換対象の文字列/置換後の文字列/g' test.txt

一行挿入する

最終行に追加&改行

echo 'hoge'>> test.txt

# 「>」一つだと新規作成になる
echo 'hoge'> test.txt

行指定で追加

sed -e '行番号i 挿入する文字列' test.txt > test_new.txt

# 例(3行目にhogeを挿入)
sed -e '3i hoge' test.txt > test_new.txt

実行権限をつける

shやexeを実行するのに必要

chmod +x ${file_path}

パーミッションの変更

chmodの引数に「アクセスクラス」+「演算子」+「アクセス型」の組み合わせで指定する

アクセスクラス 名前
a 下記すべて
u ユーザ
g グループ
o その他

ll 実行時に出力される rwxr-xr-- はユーザ、グループ、その他の順に3つづつ並んでいる

  • rwxr-xr--の意味
    • rwx:ユーザに全権限を与える
    • r-x:グループに読み込みと実行権限を与える(書き込みは不可)
    • r--:その他は読み込みのみ
演算子 意味
= 指定するアクセス型に指定
+ 指定するアクセス型を追加(権限を与える)
- 指定するアクセス型を除外(権限を除く)
アクセス型 意味
r 読み込み権限
w 書き込み権限
x 実行権限

例:-rwxr-xr-x にしたいとき

# 全部r-xにして、ユーザにだけwを追加
chmod a=r-x,u+w test.exe

数値指定のときは、アクセス型に対応する数値の合計を並べる

アクセス型 数値 意味
r 4 読み込み権限
w 2 書き込み権限
x 1 実行権限

例:-rwxr-xr-x にしたいとき

  • rwx = 4 + 2 + 1 = 7
  • r-x = 4 + 1 = 5
  • r-- = 4
chmod 754 test.exe

chmodのオプション

オプション 意味
-v 実行結果を表示
-c 変更があったら実行結果を表示(変更がなければ何も出力しない)
-R サブディレクトリとかも変更
# xxxディレクトリ配下をすべて変更&変更があったら出力
chmod -cR 754 xxx/

シンボリックリンクを作成

ln -s ${dir_path} <作成するリンク名>

実行結果をコンソールに出力しない

/dev/null へ実行結果を捨てる

unzip test.zip > /dev/null

※エラーが発生しても全部出力されないので注意

疎通確認

最後に「0% packet loss」と出れば接続成功

# 無限に出力される(Ctrl + Cで中断)
ping <IPアドレス>

# 2回確認したら終わり
ping -c2 <IPアドレス>

変数の文字置換

str=`cat xxx.txt`	# xxx.txtに書かれている文字を取得
echo ${str}	# -> abc/123 と出力

str=${str#*/}	# 最初の/までを削除
echo ${str}	# -> 123 と出力

Discussion

ログインするとコメントできます