リアクショナリーソフトウェア - by fschmidt

リアクショナリーバッシュチュートリアル


目次


イントロダクション

目次

私は本当にこのチュートリアルを書きたくありませんが、既存のBashチュートリアルがあまりにもひどいので、仕方がありません。本、ウェブサイト、YouTubeを見ましたが、どれもひどいです。基本から始めていません。無駄なものがたくさん含まれています。そして、コアコンセプトを説明していません。だから、私はこのリアクショナリープログラミングを学ぶBashレッスンのためにこれを書くしかありません。

Bashシェルの一つで、私が好むものです。MacとWindowsに焦点を当てます。Linuxは持っていませんし、嫌いなので、話しません。BashのほとんどはMacとWindowsで同じですが、異なる部分については両方を説明します。

Bashの実行

目次

Bashへのアクセス方法はオペレーティングシステムによって異なります。Macの場合、"Applications > Utilities > Terminal.app"にあるMacターミナルを通じてBashにアクセスします。デフォルトのシェルをBashに設定してください。Windowsの場合はMSYS2をインストールします。デフォルトのターミナルはあまり良くないので、Windowsターミナルを使用することをお勧めします。

はじめに

目次

MacでBashを起動すると、次のように表示されます:

Last login: Thu Jan 4 23:25:35 on ttys004 The default interactive shell is now zsh. To update your account to use zsh, please run `chsh -s /bin/zsh`. For more details, please visit https://support.apple.com/kb/HT208050. ~ $

Windows - MSYS2では、次のように表示されます:

~ $

$のある行はコマンドプロンプトです。カーソルはその末尾にあり、入力するとテキストがそこに表示されます。$の前に異なるテキストが表示されることがありますが、それは問題ありません。ただし、行は$で終わる必要があります。そうでない場合は、何かが間違っています。

「qqq」と入力してください。「何かを入力」と言った場合、最後にリターン/エンターを入力する必要があります。リターン/エンターを入力したときにのみ、Bashは入力した内容を処理します。次のように表示されるはずです:

~ $ qqq -bash: qqq: command not found ~ $

Bashは「qqq」が何を意味するのか分からず、そのように表示します。次に、以下を試してください... $の後にあるものを入力し、Bashが示すように応答するはずです。

~ $ echo hi hi ~ $ echo how are you how are you ~ $ echo bye bye

echoコマンドは、後に続くものをエコーします。次に、キーボードの上矢印を押してください。これにより、カーソルの位置に前のコマンドが表示されます。もう一度上矢印を押すと、その前のコマンドが表示されます。下矢印、左矢印、右矢印を試してください。これを使用してコマンド履歴をナビゲートできます。削除キーも行の編集に使用できます。そしてもちろん、入力できます。リターン/エンターを押すと、Bashは編集されたコマンドを取得して処理します。

echo how are youを入力すると、echoはコマンドです。このコマンドには3つの引数があります:howareyou。コマンドと引数はスペースで区切られます。スペースの数は関係ありませんので:

~ $ echo how are you how are you

echoは引数を1つのスペースで区切って返します。

~ $ echo one; echo two one two

1行に複数のコマンドを;で区切って配置できます。

「man」コマンド

目次

入力してください:

~ $ man echo

次のようなものが表示されるはずです:

ECHO(1) BSD General Commands Manual ECHO(1) NAME echo -- write arguments to the standard output SYNOPSIS echo [-n] [string ...] DESCRIPTION The echo utility writes any specified operands, separated by single blank (` ') characters and followed by a newline (`\n') character, to the stan- dard output. The following option is available: -n Do not print the trailing newline character. This may also be achieved by appending `\c' to the end of the string, as is done by iBCS2 compatible systems. Note that this option as well as the effect of `\c' are implementation-defined in IEEE Std 1003.1-2001 (``POSIX.1'') as amended by Cor. 1-2002. Applications aiming for maximum portability are strongly encouraged to use printf(1) to suppress the newline character. :

しかし、Windowsの場合、manがインストールされていないかもしれません。その場合は、次を実行してください:

~ $ pacman -S man-db

ここで説明されているようにmanをインストールし、再度man echoを試してください。

manコマンドはコマンドのドキュメントを表示します。残念ながら、キーを覚えることに基づいた愚かなユーザーインターフェースを持っているので、必要なキーだけを教えます。下矢印と上矢印は1行ずつ下と上に移動します。スペースキーは1ページ下に移動します。そして最も重要なのは、「q」を入力すると終了し、Bashに戻ります。これを覚えておく必要があります。

次にman manを入力してみてください。表示されるすべての情報が必要なわけではありませんが、複雑なmanページがどのように見えるかを確認できます。他のコマンドのドキュメントを取得するためにmanを使用できます。

ディレクトリ

目次

Mac FinderまたはWindowsファイルエクスプローラーに精通しているはずで、これからディレクトリ(「フォルダ」とも呼ばれる)がツリー状に整理されていることを知っているはずです。

Macの場合:

~ $ pwd /Users/fschmidt ~ $ open . ~ $

Windowsの場合:

~ $ pwd /home/fschmidt ~ $ explorer . ~ $

Bashを使用しているときは、常にあるディレクトリにいます。これをカレントディレクトリまたは作業ディレクトリと呼びます。pwdはこのディレクトリへのフルパスを表示します。詳細についてはman pwdを参照してください。open .はカレントディレクトリのMac Finderを開き、explorer .はカレントディレクトリのWindowsファイルエクスプローラーを開くはずです。

Macで続けます:

~ $ mkdir learn ~ $ cd learn ~/learn $ pwd /Users/fschmidt/learn

mkdirはカレントディレクトリにディレクトリを作成します。Mac FinderまたはWindowsファイルエクスプローラーで作成されたディレクトリを確認できるはずです。cdは「ディレクトリを変更する」の略です。これによりカレントディレクトリが変更されます。cdは組み込みコマンド(Bashに組み込まれている)であり、manは組み込みコマンドには役立たないため、man cdの代わりにhelp cdを試してください。続けます...

~/learn $ pwd /Users/fschmidt/learn ~/learn $ ls ~/learn $ touch file1 ~/learn $ ls file1 ~/learn $ touch file2 ~/learn $ touch file3 ~/learn $ ls file1 file2 file3 ~/learn $ mkdir dir1 ~/learn $ ls dir1 file1 file2 file3 ~/learn $ ls -F dir1/ file1 file2 file3 ~/learn $ ls -a . .. dir1 file1 file2 file3 ~/learn $ ls -a -F ./ ../ dir1/ file1 file2 file3 ~/learn $ ls -aF ./ ../ dir1/ file1 file2 file3

lsはファイルをリストし、touchは空のファイルを作成します。-で始まる引数はオプションです。使用したオプションの詳細についてはman lsを参照してください。-Fはディレクトリに「/」を追加し、-aは通常隠されている「.」で始まるファイルを表示します。オプションは組み合わせることができます。

~/learn $ ls file1 file1 ~/learn $ ls qqq ls: qqq: No such file or directory ~/learn $ ls file1 qqq file2 ls: qqq: No such file or directory file1 file2 ~/learn $ ls dir1 ~/learn $ touch dir1/d1file ~/learn $ ls dir1 d1file ~/learn $ ls -d dir1 dir1 ~/learn $ ls file1 file2 dir1 file1 file2 dir1: d1file ~/learn $ ls -d file1 file2 dir1 dir1 file1 file2 ~/learn $ ls -dF file1 file2 dir1 dir1/ file1 file2

ファイル引数なしで、lsはカレントディレクトリのファイルをリストします。ファイル引数がある場合、それらのファイルが存在する場合にリストします。ファイルがディレクトリの場合、-dオプションが使用されない限り、ディレクトリ内の内容をリストします。

~/learn $ ls dir1 file1 file2 file3 ~/learn $ ls . dir1 file1 file2 file3 ~/learn $ ls -d . . ~/learn $ ls -dF . ./ ~/learn $ ls ./file1 ./file1 ~/learn $ ls dir1 d1file ~/learn $ ls ./dir1 d1file ~/learn $ pwd /Users/fschmidt/learn ~/learn $ cd . ~/learn $ pwd /Users/fschmidt/learn

.はカレントディレクトリです。

~/learn $ pwd /Users/fschmidt/learn ~/learn $ cd dir1 ~/learn/dir1 $ pwd /Users/fschmidt/learn/dir1 ~/learn/dir1 $ ls . d1file ~/learn/dir1 $ ls .. dir1 file1 file2 file3 ~/learn/dir1 $ cd .. ~/learn $ pwd /Users/fschmidt/learn ~/learn $ cd dir1 ~/learn/dir1 $ pwd /Users/fschmidt/learn/dir1 ~/learn/dir1 $ cd ../.. ~ $ pwd /Users/fschmidt ~ $ cd learn ~/learn $ pwd /Users/fschmidt/learn

..は親ディレクトリです。

~/learn $ echo * dir1 file1 file2 file3 ~/learn $ echo d* dir1 ~/learn $ echo f* file1 file2 file3 ~/learn $ echo *1 dir1 file1 ~/learn $ echo dir1/* dir1/d1file ~/learn $ echo */* dir1/d1file ~/learn $ echo qqq* qqq*

*はファイルのワイルドカードマッチングを行います。重要なのは、Bashがワイルドカードマッチングを行い、その結果の引数をコマンドに渡すことです。echoは一致がない限り「*」を見ません。

~/learn $ ls * file1 file2 file3 dir1: d1file ~/learn $ ls -dF * dir1/ file1 file2 file3 ~/learn $ ls -dF d* dir1/ ~/learn $ ls -dF f* file1 file2 file3 ~/learn $ ls -dF *1 dir1/ file1 ~/learn $ ls dir1/* dir1/d1file ~/learn $ ls */* dir1/d1file ~/learn $ ls -dF qqq* ls: qqq*: No such file or directory

自明であるべきです。

~/learn $ pwd /Users/fschmidt/learn ~/learn $ cd ~ ~ $ pwd /Users/fschmidt ~ $ cd learn/dir1 ~/learn/dir1 $ pwd /Users/fschmidt/learn/dir1 ~/learn/dir1 $ cd ~ $ pwd /Users/fschmidt ~ $ cd ~/learn ~/learn $ pwd /Users/fschmidt/learn ~/learn $ echo ~ /Users/fschmidt ~/learn $ echo . . ~/learn $ echo .. ..

~はホームディレクトリを意味します。引数なしのcdcd ~と同じです。~はBashによってホームディレクトリに展開されます。

~/learn $ ls -ltF total 0 drwxr-xr-x 3 fschmidt staff 96 Jan 5 02:33 dir1/ -rw-r--r-- 1 fschmidt staff 0 Jan 5 02:21 file3 -rw-r--r-- 1 fschmidt staff 0 Jan 5 02:21 file2 -rw-r--r-- 1 fschmidt staff 0 Jan 5 02:21 file1

-lはこの醜い技術的な形式を提供します。ファイルが最後に変更された日付を取得します。日付の前にはファイルサイズがあります。-tは日付で降順にソートします。

最後にオートコンプリートについて説明します。echo dと入力し、リターン/エンターを押さずにタブキーを押します。これによりecho dir1/に自動補完されます。もう一度タブを押すとecho dir1/d1fileに自動補完されます。ファイルやディレクトリを入力中にタブを押すと、Bashが一致するファイル名を使用して自動補完を試みます。echo fを入力してタブを押すとecho fileになります。次にどれを選ぶべきか分かりません。もう一度タブを押すとビープ音が鳴ります。そしてもう一度タブを押すと、次のようにオプションが表示されます:

~/learn $ echo file file1 file2 file3 ~/learn $ echo file

一般的に、ファイル名を入力中にいつでもタブを押してみてください。オートコンプリートは多くの入力を節約します。

ファイルの操作

目次
~/learn $ ls -F dir1/ file1 file2 file3 ~/learn $ cp file1 copied ~/learn $ ls -F copied dir1/ file1 file2 file3 ~/learn $ mv copied moved ~/learn $ ls -F dir1/ file1 file2 file3 moved ~/learn $ rm moved ~/learn $ ls -F dir1/ file1 file2 file3

cpはファイルやディレクトリをコピーします。mvはファイルやディレクトリを移動します。rmはファイルやディレクトリを削除します。これらのコマンドの詳細についてはmanページを参照してください。

~/learn $ ls -F dir1/ file1 file2 file3 ~/learn $ mkdir dir2 ~/learn $ touch dir2/d2file ~/learn $ ls -F dir1/ dir2/ file1 file2 file3 ~/learn $ ls dir2 d2file ~/learn $ rm dir2 rm: dir2: is a directory ~/learn $ rm -d dir2 rm: dir2: Directory not empty ~/learn $ rm dir2/d2file ~/learn $ rm -d dir2 ~/learn $ ls -F dir1/ file1 file2 file3 ~/learn $ ls -F dir1/ file1 file2 file3 ~/learn $ mkdir dir2 ~/learn $ touch dir2/d2file ~/learn $ ls -F dir1/ dir2/ file1 file2 file3 ~/learn $ rm -r dir2 ~/learn $ ls -F dir1/ file1 file2 file3 ~/learn $ ls -F dir1/ file1 file2 file3 ~/learn $ cp dir1 dir2 cp: dir1 is a directory (not copied). ~/learn $ cp -r dir1 dir2 ~/learn $ ls -F dir1/ dir2/ file1 file2 file3 ~/learn $ ls dir2 d1file ~/learn $ cp f* dir2 ~/learn $ ls dir2 d1file file1 file2 file3 ~/learn $ rm -r dir2 ~/learn $ ls -F dir1/ file1 file2 file3 ~/learn $ ls -F dir1/ file1 file2 file3 ~/learn $ mkdir dir2 ~/learn $ cp -r dir1 dir2 ~/learn $ ls -F dir2 dir1/ ~/learn $ ls -F dir2/dir1 d1file ~/learn $ rm -r dir2 ~/learn $ ls -F dir1/ file1 file2 file3

これをすべて説明することもできますが、しません。manを使用してコマンドとそのオプションを理解し、それらを試してみてください。完全に理解するまで続けないでください。

引用

目次
~/learn $ echo a b a b ~/learn $ echo "a b" a b ~/learn $ echo 'a b' a b ~/learn $ echo "a b" c a b c

Bashは引用符内のテキストを1つの引数として扱います。したがって、echo a bでは、echoには2つの引数があります:「a」と「b」。echo "a b"では、echoには1つの引数があります:「a b」。echo 'a b'では、echoには1つの引数があります:「a b」。echo "a b" cでは、echoには2つの引数があります:「a b」と「c」。

~/learn $ echo a\ \ \ b a b

引用符の外では、\ は区切り文字として扱われず、引数の一部としてスペース文字として扱われます。

変数

目次
~/learn $ echo $X ~/learn $ X="some text" ~/learn $ echo $X some text ~/learn $ echo "X is: $X" X is: some text ~/learn $ echo 'X is: $X' X is: $X ~/learn $ X="$X and more" ~/learn $ echo $X some text and more

ここでXは変数です。$Xでその値を取得します。これはダブルクォート内でも機能しますが、シングルクォート内では機能しません。

Bashで使用される特別な変数である環境変数があります。

~/learn $ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/fschmidt/Dropbox/bin:/Users/fschmidt/hg/luan/scripts:/usr/local/opt/postgresql@9.5/bin ~/learn $ which ls /bin/ls ~/learn $ cd /bin /bin $ pwd /bin /bin $ ls [ dd launchctl pwd test bash df link rm unlink cat echo ln rmdir wait4path chmod ed ls sh zsh cp expr mkdir sleep csh hostname mv stty dash kill pax sync date ksh ps tcsh /bin $ ls -F [* dd* launchctl* pwd* test* bash* df* link* rm* unlink* cat* echo* ln* rmdir* wait4path* chmod* ed* ls* sh* zsh* cp* expr* mkdir* sleep* csh* hostname* mv* stty* dash* kill* pax* sync* date* ksh* ps* tcsh* /bin $ cd ~/learn ~/learn $

PATHはBashがコマンドを検索するディレクトリのリストを:で区切って含む環境変数です。whichコマンドはコマンドへのフルパスを表示します。ls -Fは実行可能ファイルに*を追加します。

~/learn $ subl file1 -bash: subl: command not found ~/learn $ "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" file1 ~/learn $ PATH="$PATH:/Applications/Sublime Text.app/Contents/SharedSupport/bin" ~/learn $ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/fschmidt/Dropbox/bin:/Users/fschmidt/hg/luan/scripts:/usr/local/opt/postgresql@9.5/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin ~/learn $ subl file1 ~/learn $

ここでは、最初にフルパスを使用してSublime Textでファイルfile1を編集し、次にディレクトリをPATHに追加してBashがsublを見つけられるようにします。

WindowsではMicrosoft Wordを持っています。Windowsコマンドプロンプト(Bashではなく)から:

C:\Users\fschmidt>winword C:\Users\fschmidt>where winword C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE

winwordはMicrosoft Wordを実行します。コマンドプロンプトのwhereコマンドはBashのwhichコマンドのようなものです。では、MSYS2で:

~ $ winword bash: winword: command not found ~ $ echo $PATH /usr/local/bin:/usr/bin:/bin:/opt/bin:/c/Windows/System32:/c/Windows:/c/Windows/System32/Wbem:/c/Windows/System32/WindowsPowerShell/v1.0/:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/c/Program Files/TortoiseHg:/c/Program Files/Java/jdk1.8.0_202/bin ~ $ PATH="$PATH:/c/Program Files/Microsoft Office/root/Office16" ~ $ echo $PATH /usr/local/bin:/usr/bin:/bin:/opt/bin:/c/Windows/System32:/c/Windows:/c/Windows/System32/Wbem:/c/Windows/System32/WindowsPowerShell/v1.0/:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/c/Program Files/TortoiseHg:/c/Program Files/Java/jdk1.8.0_202/bin:/c/Program Files/Microsoft Office/root/Office16 ~ $ winword ~ $

Macに戻ると、Finderの「アプリケーション」にあるアプリケーションをコマンドとしてではなくアプリケーションとして実行する別の方法があります。

~/learn $ open -a 'Sublime Text' file1

もう1つの便利な環境変数はPS1で、コマンドプロンプトを制御します。私はすでにこれを設定していますが、していない場合:

Franklins-MacBook-Pro:learn fschmidt$ echo $PS1 \h:\W \u\$ Franklins-MacBook-Pro:learn fschmidt$ PS1="\w $ " ~/learn $ echo $PS1 \w $ ~/learn $

「bash PS1」をGoogleで検索してください。

.bash_profile

目次
~/learn $ cd ~ $ ls .bash_profile .bash_profile

もし.bash_profileが見つからない場合は、touch .bash_profileを実行して作成してください。このファイルには、Bashが起動したときに実行されるBashコマンドが含まれています。すでにこのファイルがある場合、#で始まるコメントが含まれている可能性があります。コメントは無視されます:

~ $ # コメント行、何もしません ~ $ echo whatever # 行末コメント whatever ~ $

Macで.bash_profileを編集するには、次を実行できます:

~ $ open -a 'Sublime Text' .bash_profile

Windowsで.bash_profileを編集するには、次を実行できます:

~ $ notepad .bash_profile

次の行を.bash_profileに追加してみてください:

echo hello there

新しいBashターミナルを開くと、「hello there」が表示されるはずです。.bash_profileは、新しいBashターミナルを開くことでBashが開始されたときに実行されます。

私はPS1PATH.bash_profileに設定して、望むコマンドプロンプトとアクセスしたいコマンドを持つようにしています。Sublime TextコマンドsublPATHで利用可能にすることをお勧めします。

「find」コマンド

目次
~/learn $ find . . ./file3 ./file2 ./file1 ./dir1 ./dir1/d1file ~/learn $ find . -name 'file*' ./file3 ./file2 ./file1 ~/learn $ find . -name '*file' ./dir1/d1file ~/learn $ find . -name 'd*' ./dir1 ./dir1/d1file ~/learn $ find . -name '*1' -or -name '*2' ./file2 ./file1 ./dir1

findはディレクトリツリー内のファイルを再帰的に検索します。この場合、*のワイルドカードマッチングはBashによって行われているのではなく、findによって行われています。findにはファイルを検索し、それに対してアクションを実行するための多くのオプションがあります。man findを参照してください。

入力と出力

目次
~/learn $ echo 'this is a test' >test.txt ~/learn $ ls -F dir1/ file1 file2 file3 test.txt ~/learn $ cat test.txt this is a test ~/learn $ echo 'this is another test' >test.txt ~/learn $ cat test.txt this is another test ~/learn $ echo 'another line' >>test.txt ~/learn $ cat test.txt this is another test another line ~/learn $ cat <test.txt this is another test another line ~/learn $ cat <<End >test.txt > I am typing this > and this > End ~/learn $ cat test.txt I am typing this and this ~/learn $ (echo one; echo two) >test.txt ~/learn $ cat test.txt one two

すべてのプログラムには標準入力、標準出力、標準エラーがあります。プログラムは通常の出力を標準出力に書き込み、エラーメッセージを標準エラーに書き込みます。デフォルトでは、標準入力はターミナルから来て、標準出力と標準エラーはターミナルに行きますが、これを変更できます。>fileは標準出力をfileに送ります。>>fileは標準出力をfileに追加します。<fileは標準入力をfileから読み込みます。<<whateverwhateverだけの行が来るまで続くテキストから標準入力を読み込みます。コマンドは()の間で組み合わせることができます。catの動作を理解するためにman catを必ず行ってください。

~/learn $ ls >ls.txt ~/learn $ cat ls.txt dir1 file1 file2 file3 ls.txt test.txt ~/learn $ ls -d f* q* >ls.txt ls: q*: No such file or directory ~/learn $ cat ls.txt file1 file2 file3 ~/learn $ ls -d f* q* 2>ls.txt file1 file2 file3 ~/learn $ cat ls.txt ls: q*: No such file or directory ~/learn $ ls -d f* q* | tee ls.txt ls: q*: No such file or directory file1 file2 file3 ~/learn $ cat ls.txt file1 file2 file3 ~/learn $ ls -d f* q* 2>&1 | tee ls.txt ls: q*: No such file or directory file1 file2 file3 ~/learn $ cat ls.txt ls: q*: No such file or directory file1 file2 file3

2>fileは標準エラーをfileに送ります。|は前のコマンドの標準出力を次のコマンドの標準入力に送ります。2>&1は標準エラーを標準出力に送ります。tee fileは標準入力を読み取り、それを標準出力とfileの両方に書き込みます。

~/learn $ find . -type f | wc -l 6

learnには6つのファイルがあります。これがどのように機能するかを理解するためにmanを使用してください。

コントロールキー

目次
~/learn $ sleep 3 ~/learn $ sleep 30 ^C ~/learn $

sleep 3は3秒間スリープします。つまり、3秒間何もしません。このコマンドが終了するのを3秒待ちました。次にsleep 30を実行しましたが、30秒間スリープするはずでしたが、我慢できずにcontrol+cを押してプログラムを中断し、抜け出しました。コマンドが終了するのを待っているときに行き詰まった場合は、control+cを試してみてください。

~/learn $ wc I am typing this and this now I will end my input with control+d 3 14 65 ~/learn $ wc this time I will use control+c to break out ^C ~/learn $

Control+dは入力の終了を意味します。

コマンド置換

目次
~/learn $ echo I am in $(pwd) I am in /Users/fschmidt/learn ~/learn $ echo this directory contains: $(ls) this directory contains: dir1 file1 file2 file3 ls.txt test.txt ~/learn $ echo this directory contains $(ls | wc -l) files this directory contains 6 files

cmd $(commands)commandsの出力をcmdの引数テキストとして使用します。

~/learn $ cat $(find . -type f) | wc -c 86

learnのファイルには合計86バイトが含まれています。これがどのように機能するかを理解するためにmanを使用してください。

アンパサンド

目次
~/learn $ (sleep 5; echo done) & [1] 10080 ~/learn $ echo waiting waiting ~/learn $ done [1]+ Done ( sleep 5; echo done ) ~/learn $

通常、Bashはコマンドが完了するのを待ってからコマンドプロンプトを表示し、入力を許可します。しかし、コマンドラインの末尾に&を付けると、bashは待たずにコマンドを別のプロセスで実行します。上記の~/learn $ echo waitingでは、echo waitingを入力しました。しかし、~/learn $ doneでは、doneを入力しませんでした。代わりに、これは5秒後にecho doneによって生成されました。[1] 10080はプロセスが開始されたことを示し、[1]+ Done ( sleep 5; echo done )はプロセスが終了したことを示します。

これは、コマンドが終了するのを待ちたくない場合に便利です。Windowsでこれを考えてみてください:

~ $ notepad

ここでは、Bashがこのコマンドの終了を待っているため、Notepadを終了するまでコマンドプロンプトを再度取得できません。代わりに次を実行します:

~ $ notepad & [1] 2010 ~ $

これでNotepadが実行され、Bashを続けて使用できます。

シェルスクリプト

目次

test.shというファイルを作成し、次の内容を含めます:

echo this is a shell script

次にBashから:

~/learn $ cat test.sh echo this is a shell script ~/learn $ ./test.sh -bash: ./test.sh: Permission denied ~/learn $ ls -F test.sh test.sh ~/learn $ chmod +x test.sh ~/learn $ ls -F test.sh test.sh* ~/learn $ ./test.sh this is a shell script ~/learn $

chmod +x filefileを実行可能にして実行できるようにします。次にtest.shを編集します

~/learn $ # edit test.sh ~/learn $ cat test.sh nonsense echo this is a shell script ~/learn $ ./test.sh ./test.sh: line 1: nonsense: command not found this is a shell script ~/learn $ # edit test.sh ~/learn $ cat test.sh set -e nonsense echo this is a shell script ~/learn $ ./test.sh ./test.sh: line 2: nonsense: command not found ~/learn $

デフォルトでは、スクリプトはエラー後も実行を続けます。長いスクリプトでは、エラー後にスクリプトを終了させたいです。set -eはこれを行います。help setを参照してください。

~/learn $ X=some ~/learn $ echo $X some ~/learn $ echo $Xthing ~/learn $ echo ${X}thing something ~/learn $ # edit test.sh ~/learn $ cat test.sh echo "\$* = $*" echo "\$# = $#" echo "\$0 = $0" echo "\$1 = $1" echo "\$2 = $2" echo "\$3 = $3" echo "\$4 = $4" echo "\$14 = $14" echo "\${14} = ${14}" echo "\$@ = $@" ./count.sh "$*" ./count.sh "$@" ~/learn $ ./test.sh a b "c d" $* = a b c d $# = 3 $0 = ./test.sh $1 = a $2 = b $3 = c d $4 = $14 = a4 ${14} = $@ = a b c d 1 3 ~/learn $ cat count.sh echo $# ~/learn $

Bashスクリプトには特別に定義された変数があります。$*$@の違いは微妙で、通常は$*を使用します。$*はすべての引数を1つの文字列として返し、$@は引数を個別に返しますが、この違いはほとんど影響を与えません。

変数とスクリプト

目次
~/learn $ X=value ~/learn $ echo $X value ~/learn $ # edit test.sh ~/learn $ cat test.sh echo "\$X = $X" ~/learn $ ./test.sh $X = ~/learn $ export X ~/learn $ ./test.sh $X = value

変数は現在のシェルで定義されます。シェルスクリプトは独自のシェルで実行されます。したがって、デフォルトでは、ターミナル/親シェルで定義された変数を参照しません。export varvarを子プロセスで利用可能にします。つまり、シェルスクリプトで利用可能にします。.bash_profileexport PATHを行うことをお勧めします。これにより、PATHがスクリプトで利用可能になります。

~/learn $ X=terminal ~/learn $ echo $X terminal ~/learn $ # edit test.sh ~/learn $ cat test.sh X=script export X ~/learn $ ./test.sh ~/learn $ echo $X terminal ~/learn $ . test.sh ~/learn $ echo $X script

変数を親から子にエクスポートできますが、子から親にはできません。. scriptはファイルscriptのテキストを現在のシェルに含めます。この場合、別のシェルで実行されません。これがスクリプトでターミナルシェルに変数を設定する唯一の方法です。

~/learn $ pwd /Users/fschmidt/learn ~/learn $ # edit test.sh ~/learn $ cat test.sh cd ~ ~/learn $ ./test.sh ~/learn $ pwd /Users/fschmidt/learn ~/learn $ . test.sh ~ $ pwd /Users/fschmidt ~ $ cd learn ~/learn $

これは./script. scriptの違いを示しています。

あなたのスクリプト

目次
~/learn $ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/fschmidt/Dropbox/bin:/Users/fschmidt/hg/luan/scripts:/usr/local/opt/postgresql@9.5/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin ~/learn $ echo ~/Dropbox/bin /Users/fschmidt/Dropbox/bin ~/learn $ ls -F ~/Dropbox/bin/e /Users/fschmidt/Dropbox/bin/e* ~/learn $ cat ~/Dropbox/bin/e open -a 'Sublime Text' $* ~/learn $ e test.sh ~/learn $

役立つスクリプトを書くときは、それらをディレクトリに入れ、そのディレクトリをPATHに追加します。私は~/Dropbox/binを使用しており、そこにeという名前のスクリプトがあります。これにより、コマンドラインからファイルを編集できます。e test.shはコマンドラインからtest.shを編集できます。

Bashはスクリプトを探すときに、明示的なパスを指定しない限り、PATH内のスクリプトのみを探します。

~/learn $ # edit test.sh ~/learn $ cat test.sh echo this is a shell script ~/learn $ test.sh -bash: test.sh: command not found ~/learn $ ./test.sh this is a shell script ~/learn $

test.shを単独で呼び出すと失敗します。これはPATHにないためです。しかし、./test.shは明示的なパスであるため機能します。

高度なスクリプト

目次

ここにWord DOCXファイルを解凍するundocx.shというより高度なスクリプトがあります。

#!/bin/bash set -e if [ $# -ne 1 ]; then echo "usage: $0 filename" exit 1 fi FILE="$1" NEWDIR=$(basename $FILE .docx) mkdir $NEWDIR unzip $FILE -d $NEWDIR export XMLLINT_INDENT=$'\t' for file in $(find $NEWDIR -name "*.xml" -o -name "*.rels"); do mv "$file" temp.xml xmllint --format temp.xml >"$file" done rm temp.xml

Bashは通常の機能をすべて含む完全なプログラミング言語です。私のスクリプトのいくつかのコマンドはmanでよく説明されていますが、いくつかはそうではありません。特にifforのドキュメントは不十分です。このような場合、ChatGPTに次のように尋ねることをお勧めします:

Bashの「if」文を説明してください。 Bashの「for」文を説明してください。

ChatGPTはBashをよく知っています。ChatGPTに詳細を説明してもらうことを信頼していますが、コアコンセプトを説明することは信頼していません。Googleを試すこともできますが、ChatGPTは現代のプログラマーよりも優れています。

結論

目次

Bashの使用の少なくとも90%は、ターミナルに入力する単純なコマンドです。できるだけBashを使用し、GUIを使用せずに練習してください。システム管理者にならない限り、高度なスクリプトをあまり使用しません。しかし、コアの基本をしっかりと理解していれば、必要に応じて高度なスクリプトを読み書きする方法を理解できるはずです。