盆暗の学習記録

データサイエンス ,エンジニアリング,ビジネスについて日々学んだことの備忘録としていく予定です。初心者であり独学なので内容には誤りが含まれる可能性が大いにあります。

Bash・Shellコマンドまとめ

bash操作・シェルスクリプトについて学んだのでメモ。

ファイル操作系コマンド

カレントディレクトリ関係

# カレントディレクトリの確認
pwd

# change directory
cd [path]

# ls:ファイル一覧
ls

# la -la
# -l:ファイルのサイズや更新日時を含めた一覧
# -a:隠しファイルを含めた一覧
ls -la

フォルダ/ファイルの操作

# mkdir:フォルダ作成
mkdir [dir]
# mkdir -p:深いディレクトリを一気に作成
mkdir -p learning/log/20190422.md

# touch:ファイル作成
touch [file]

# rm:ファイル・ディレクトリの削除
rm (option) [削除するファイル1] [削除するファイル2] ...
# rm -i:「本当に削除しますか?」と確認してくれる
# rm -r:フォルダを削除できる

# rmdir:空のディレクトリを削除する
rmdir [dir] # 空でないディレクトリを指定するとエラーになる

# mv:ファイル・ディレクトリを移動する/名前を変更する
mv (option) [移動元] [移動先]

ファイルの内容を表示

# cat:ファイルの内容を表示
cat [file]

# head:ファイルの最初の10行を表示
head [file]

その他のコマンド

curl:URLへのアクセス・ダウンロード

curl -o <ファイル名> <URL>

-o でファイルへの書き出し

# ダウンロード
curl -o hogehoge.tar.gz http://xxxxxxxxxxx.jp/hogehoge.tar.gz
# 解凍
tar xzf hogehoge.tar.gz

find:ディレクトリツリーからファイルを探す

find <検索開始ディレクトリ> <検索条件> <アクション>
# カレントディレクトリで,.txtファイルを調べ,パスを表示(print)する
find . -name "*.txt" -print
  • printは省略可能(デフォルトがprint)

ヘルプ

# ヘルプ
[command] --help

# マニュアル
man [command]

# コマンドのフルパスを表示する
which [command]

環境変数

# printenv:環境変数の表示
printenv
# あるいは特定の変数を指定してecho
echo $LANG

# export:環境変数の設定
export LANG='ja_JP.UTF-8'

シェルスクリプト

シェルスクリプトの実行方法や注意点

Windowsで書く際の注意点

  • 改行コードがCRLFで作成すると,Linuxは改行コードがLFなので,エラーになる
    • VSCodeなどでWindowsを通して書く場合,LFとして保存する必要がある

#!/bin/bash:シバン

シェルスクリプトを作るとき,最初の行に以下のように書く必要があるらしい。

#!/bin/bash

これは,その.shファイルを,/bin/bashで実行するよう指示していることになる(Linuxカーネルは#!の後ろのコマンドを実行する)。

つまり,以下のようなコマンドラインが実行されているということになる

$ /bin/bash ./hoge.sh

シェルスクリプトの3つの実行方法

いろんな実行方法があるらしい。

①シェルの引数として実行する

bashから実行させる。shファイルに実行権限は不要

bash hoge.sh

②sourceコマンドを利用して実行する

sourceコマンド,あるいはドットコマンドで実行できる

sourceコマンドでは直接実行するわけではないので,shファイルに実行権限は不要

source ./hoge.sh
. ./hoge.sh

ドットコマンドは古いやり方だし,見落として妙なトラブルを引き起こしかねないため非推奨らしい

③ファイル名のみを指定して実行する

シェルスクリプトに実行権限を付与すると,sourceコマンドが不要になる

# 実行権限の付与
chmod +x hoge.sh
# 実行
./hoge.sh

変数

変数に関しての注意点

  • 代入するときは= の前後にスペースを入れてはならない
  • 代入時は$をつけないが,呼び出すときは$をつける

$():コマンド置換

コマンド置換$()により,コマンドの結果を文字列として受け取る

# dateコマンドで取得した日付を文字列として受け取る
today=$(date '+%Y-%m-%d')

${}:変数を文字列に埋め込む

"string${var}string"

# 今日の日付
today=$(date "+%Y年%m月%d日")
# 文字列の結合
message="今日は${today}です!"
# 表示
echo $message

if文とfor文

if文

if 文と test コマンド | UNIX & Linux コマンド・シェルスクリプト リファレンス

testコマンド

論理演算はtestコマンドか[コマンドを使う。次のif文は同じ意味になる。

if [ "$1" = "bin" ]; then
if test "$1" = "bin"; then

シェルスクリプトでは,ifの後に置くのは条件式ではなくコマンドである

$ type [
[ is a shell builtin

hoge="A"
fuga="A"
if [ $hoge -eq $fuga ]; then # -eqと=は同じ意味の論理演算子
  echo "文字列は同じです"
else
  echo "文字列は違います"
fi

for文

shell - How do I iterate over a range of numbers defined by variables in Bash? - Stack Overflow

for i in {1..5}
do 
    echo $i # 変数iの値を表示
done
1 
2 
3 
4 
5

例:Fizz Buzz

  • for ((i=1;i <= $N;i++))C言語風に1からNまで1ずつ変化するi を指定できる
  • $((計算式))で計算でき,剰余は%で計算する
#!/bin/bash
N=30
for ((i=1;i <= $N;i++)); do
    if [ $(($i % 15)) = 0 ]; then
        echo "Fizz Buzz"
    elif [ $(($i % 5)) = 0 ]; then
        echo "Buzz"
    elif [ $(($i % 3)) = 0 ]; then
        echo "Fizz"
    else
        echo $i
    fi
done

配列

bash 配列まとめ - Qiita

# 空の配列の生成
empty_array=()

# 先頭に追加
array=(3 "${array[@]}")        # array は (3 “a” "b" "c")
# 末尾に追加
array=("${array[@]}" 4)        # array は (3 "a" "b" "c" 4)
array+=( 5 )                   # array は (3 "a" "b" "c" 4 5)

例:lsコマンドの中身を配列にして表示する

#!/bin/bash
array=()
for i in `ls`; do
    array+=( $i )
done
echo ${array[@]}

例:その日の日付をファイル名に含んだ空のファイルを作成する

#!/bin/bash
# 保存先
directory="./log"
# カレントディレクトリの移動
cd ${directory} 

# ファイル名
today=$(date "+%Y%m%d")
filename="log_${today}.log"

# もしファイルがなければ作成する
if [ -e $filename ]; then
    echo "既にファイルが存在します。"
else
    touch "${filename}"
    echo "${directory}に${filename}を作成しました。"
fi

引数

コマンドの引数は,コマンドからスペースを空けて記述していく。

bash hoge.sh 引数1 引数2 ... 引数n
  • $0, $1, ..., $nで参照できる
    • \エスケープできる
  • $@:すべての引数を1行であつかうが,それぞれ別の文字列
    • 別のコマンドの引数としてそのまま渡すときに便利
  • $*:引数を分割せず,スペース区切りされた1つの文字列とする
  • $#で指定されたパラメータの数がカウントされる
  • ./hoge.sh *のように*を指定すると,カレントディレクトリにあるファイル達の名前がパラメータに入る

例:引数をそのままechoする

#!/bin/bash
echo "指定された引数(\$@):$@"
echo "指定された引数の数(\$#):$#"

標準入力・出力

read:標準入力

入力と出力 | UNIX & Linux コマンド・シェルスクリプト リファレンス

  • catでファイル名を指定しない場合,標準入力を受け取ってechoする動きをするようになる
  • readコマンドで標準入力を受け取るようになる
# 標準入力の受け取り
read [変数名]
# 入力された内容は[変数名]の変数に格納される
echo $[変数名]

echo:標準出力

# 標準出力
echo [object]

$ echo Hello World
Hello World

リダイレクト

# 標準入力
cat < [file]
# 標準出力
ls > ls.txt
## >:上書き,>>:末尾に追記
ls -la >> ls.txt
# 標準エラー出力
ls /xxx 2> error.txt
  • 上のコードで作られたls.txtはメモ帳で開くと改行が無いが,cat < ls.txtすると改行されて表示される

その他の概念

パイプライン

  • コマンドからの標準出力を,別のコマンドの標準入力に入れる
# ls -laの結果をlessで表示する
ls -la | less

相対パス絶対パス

例:相対パス絶対パスをパラメータで渡し、渡されたファイルパスが相対か絶対かを判定する

#!/bin/bash
# 第一引数にパスを入れてもらう
if [ $# != 1 ]; then
    echo "第一引数に判定したいパスを入れてください。"
else
    # 1文字目を取り出す
    first_letter=$( echo $1 | cut -c 1 )

    if [ $first_letter = "/" ]; then
        echo "絶対パスです。"
    else
        echo "相対パスです。"
    fi
fi

文字列操作

grep:文字列検索

grep [オプション] <検索パターン> <ファイル名>
# シェルスクリプトを検索
ls -la | grep .sh

文字列置換

sedによる置換

sed "s/置換対象にしたいパターン/置き換えたい新しいパターン"

変数内文字列置換

${変数/検索文字列/置換文字列}

参考

この本を参考にしていました。この一冊で全部をまかなえる…とまでは行きませんが,多くの基本的なコマンドをカバーしている上,「なぜこうするのか」についての説明もあったりして,いい本でした。

新しいLinuxの教科書

新しいLinuxの教科書