シェルスクリプトで使用された変数をスクリプトの最後から削除できますか?
rm -rf $abc
rm -rf $def
または
unset $abc
unset $def
など。
これは本当に良い習慣ですか?
答え1
これはとても悪い慣行。
rm
ファイルの削除。これは変数とは関係ありません。それにもかかわらず、スクリプトが終了し、オペレーティングシステムがシェルのメモリを回復すると、変数自体は解放されます。
単純なケースでは、変数のいずれかの値と同じ名前のファイルが次の構成によって削除されます。
abc=filename
rm -f $abc # Deletes "filename" in the current directory
状況はさらに悪化します。ファイル名が含まれてabc
いる場合def
スペースで区切られた個々の単語(または他の文字)、これらのファイルを削除してワイルドカードが単語に表示されると、IFS
ワイルドカードも拡張されます。*
abc='hello world'
rm -f $abc # Deletes file "hello" and "world" (leaves "hello world" alone)
abc='5 * 3'
rm -f $abc # Deletes all files, because * is expanded (!)
def='-r /'
rm -f $def # Really deletes *all* files this user can access
シェルパラメータは次に拡張されます。$var
〜によって噴射ここで、変数の各文字はIFS
変数を異なるパラメータに分割します。それからすべての言葉はファイル名拡張子の影響を受ける*
、?
およびパターンを使用して[abc...]
ファイル名を作成します。変数の内容によっては、状況が本当に悪くなることがあります。これをしないでください。
空にする必要はありません。未設定何らかの方法でシェルスクリプトの最後に変数を追加します。
答え2
実際にはシェル変数または一時ファイルを意味するのかどうか疑問に思います。
現在実行中のタスクが次の場合(一時ファイル):
tmp=$(mktemp)
something > "$tmp"
something else < "$tmp"
rm "$tmp"
もちろん、作業が終わったら一時ファイルを削除してください。スクリプトが途中でクラッシュしても、ファイルはそのまま残りますが、これはまれではありません。必要trap 'rm -f -- "$tmp"' EXIT
に応じて、シェルの終了時にファイルを削除できます。
ただし、個々のファイルを削除するときは、-f -r`を使用してくださいrm -f -- "$tmp", as
。would help in avoiding error messages if the file was e.g. removed earlier for some reason. No reason to use
mktemp
(また、基本的に「良い」ファイル名を生成しても、その変数を引用することを忘れないでください。)
しかし、これを行うと(変数):
read var
do something with "$var"
rm "$var"
だからあなたはしたくない:削除するファイルがなく、ユーザー入力のみがあります。シェルが終了すると、シェル変数は存在しなくなり、設定を解除する必要はありません。
ただし、スクリプトが別のシェルからインポートされた場合(または .bashrc
同様のシェルにある場合)、スクリプトが終了してもシェルは終了しません。この場合、unset
最後に使用した一時変数を維持し、残りのシェルの存続期間中にその設定を維持しないことが便利です。
# in .bashrc
__hour=$(date +%H)
if [ "$__hour" -lt 12 ] ; then echo "Good Morning!" ;
elif [ "$__hour" -gt 18 ] ; then echo "Good Evening!" ;
fi
unset __hour
変数名はこのスクリプトの外で使用されている一部の変数とまだ競合する可能性があるため、名前を付けるときは注意が必要です。
答え3
今日、シェルスクリプトのエラー出力がブロックされました。その理由は、エクスポートされた環境変数が実際にシェルスクリプトにこっそり入り、不快な副作用を引き起こす可能性があるためです。具体的な方法は次のとおりです。
#!/bin/sh
#
line="$line $1"
echo $line
で呼び出すと、myscript.sh smeagol
すでにエクスポートされたline
変数が密かに入ってきます。unset line
スクリプト項目の汚染を防ぐ必要があります。
答え4
スクリプトの最後にすべての変数を設定解除するのは良い習慣ですか?1
シェルスクリプトはさまざまな方法で実行できます(以下の「1.シェルスクリプトを呼び出す方法」セクションを参照)、これはユースケースと意図によって異なります。これは、変数が元のシェル(シェルを呼び出したシェル)によって保持されているかどうかに影響します。スクリプト)かどうか。
たとえば、ting変数のいくつかのケースは次のとおりですunset
。
悪い、このスクリプトの焦点は、環境変数を設定することです。サム
そして、これもシェルスクリプトの呼び出し方法によって異なります(セクション1を参照)。
悪い、このスクリプトはシェル変数を公開するように設計されています。何らかの目的で。
例えば、スクリプトはより大きな「シェルスクリプトのコレクション」内の「モジュール」であり、他のシェルスクリプトはいわゆる「サブスクリプト」によって設定される変数に依存する。 (前の項目と同じ注意事項が適用されます。セクション1を参照してください。)
いいね、誰でも欲しいなら無知なユーザーを保護する(本人含む)と
->
前の事項が適用されない場合<-
(そうでない場合が多い)。注:無知=知識が少ない
たとえば、すべてのシェル変数が列挙される「設定解除セクション」(参照はい)時間と将来の痛みを軽減します。私は毎日シェルスクリプトを書いていませんし、執筆中に多くのコメントを残しますが、私の手の筋肉の記憶はスクリプトをどのように実行するのか気にしません。セッション(下記の「1.シェルスクリプトの呼び出し方法」のセクションをもう一度参照してください)。また、良い文書であっても、他の人がスクリプトを使用すると予想される場合は役に立ちません。これはしばしば無視されるからです(私の無知な自己を含む)。
(私は何を見逃していますか?)
1. シェルスクリプトの呼び出し方法
TL;DR
(サイトがマークダウンテーブルをサポートしていないため、ASCIIテーブル。この回答のより良い形式のバージョンを参照してください。この点.)
| Shell script calling | Preserves | Relevant |
| method | variables and | section |
| | exports | |
| --------------------------- | --------------- | --------- |
| `<interpreter> <file_name>` | no | 1.1 |
| `.` | yes | 1.2 | (workaround in 1.2.1)
| executable script | no | 1.3 |
| `source` | yes | 1.4 | (workaround in 1.2.1)
1.1<interpreter> <file_name>
たとえば、スクリプトを呼び出しscript.sh
てそのスクリプトを含むディレクトリから呼び出すとします。
-
sh script.sh
bash script.sh
-
zsh script.sh
fish script.sh
この方法はサブシェル(高度なBashスクリプトガイド:第21章。サブシェル)、これは子プロセスの新しいシェルです。
シェルと環境変数廃棄されますスクリプトの実行が完了した後にスクリプトを呼び出したシェルは影響を受けません。
スクリプトのポイントが現在のシェルで使用する環境変数を設定することである場合は、次のようにします。
1.2個dot( .
) POSIX 標準コマンド
関連トピック:stackoverflow
処置: シェルスクリプトの完了後に環境変数を保持します。
.
します」現在の環境でコマンドを実行する"(POSIX規格、ドットのマニュアルページ) 起動せずにサブシェル。
シェルと環境変数有効なままスクリプトの実行が完了した後。
同じスクリプトを再実行すると、予期しない動作が発生する可能性があります。たとえば、次のスクリプトが与えられたら(と呼びますtest.sh
)
#!/usr/bin/env bash
# https://unix.stackexchange.com/questions/129391/passing-named-arguments-to-shell-scripts
while [ $# -gt 0 ]; do
case "$1" in
--option_a|-a)
OPTION_A=$2
;;
--option_b|-b)
OPTION_B=$2
;;
*)
printf "***************************\n"
printf "* Error: Invalid argument.*\n"
printf "***************************\n"
exit 1
esac
shift
shift
done
# Setting default value if script is not called with `--option`
OPTION_A="${OPTION_A:-"default A"}"
OPTION_B="${OPTION_B:-"default B"}"
echo "OPTION_A: ${OPTION_A}"
echo "OPTION_B: ${OPTION_B}"
セクション1.1と1.3で説明されている方法で実行すると、すべてが正常です。
$ chmod +x test.sh
$ ./test.sh
OPTION_A: default A
OPTION_B: default B
$ bash test.sh -a 27
OPTION_A: 27
OPTION_B: default B
$ ./test.sh
OPTION_A: default A
OPTION_B: default B
ただし、変数のデフォルト値を使用するには(コマンドラインオプションが次の場合)または.
(以下のセクション1.4を参照)を使用します。source
いいえ場合:
# source test.sh === . ./test.sh
$ source test.sh
OPTION_A: default A
OPTION_B: default B
$ . ./test.sh -a 27
OPTION_A: 27
OPTION_B: default B
$ source test.sh
OPTION_A: 27
OPTION_B: default B
1.2.1現在のシェルを台無しにせずに.
(and)を使用する方法は?source
括弧((
および)
)を使用すると、その間のコマンドがサブシェル(セクション1.1と1.3と同じ方法)。
たとえば、( source test.sh )
。
関連文書とスレッド:
- bash のマニュアルページ > SHELL 構文 > 複合コマンド
- POSIX 標準、2.9.4 複合コマンド
unix&linux
:スクリプトをサブシェルとして実行できますか?unix&linux
:コマンドラインで括弧をどのように解釈しますか?
1.3 スクリプトファイルの実行可能ビットの設定
上記の「1.1」の説明を参照してください<interpreter> <file_name>
。
関連トピック:unix&linux
:Bashにsource
実行ビットが必要ない理由は何ですか?
たとえば、スクリプトを呼び出しscript.sh
てそのスクリプトを含むディレクトリから呼び出すとします。
$ chmod +x script.sh
$ ./script.sh
1.4source
コマンド
ポイントの同義語(.
'1.2参照)ドット(.
)POSIX標準コマンド」セクションの上)。
私が知っている限り、この同義語はbash、fish、zshにありますが、他のシェルにも存在するかもしれませんが、source
移植性のためによく使用されます。.
関連トピック:unix&linux
:ソースのエイリアスとしてドット(.)を使用するのはなぜですか?なぜ他のコマンドにショートカットがないのですか?
脚注
[1]:質問をもう一度言うと、ここの答えは変数に焦点を当て、rm
変数を設定解除しないからです。要約する:
rm
ファイルの削除unset
これは
$
次の目的に使用されます。パラメータ拡張(GNU Bashドキュメント、3.5.3シェルパラメータの拡張)この場合2、以前は必要ありませんでした。それ以外の場合は、参照しているコンテンツをvariable_name
設定解除しようとします。variable_name
$ abc=27 $ def=abc $ echo "abc=${abc}; def=${def}" abc=27; def=abc # v $ unset $def # ^ $ echo "abc=${abc}; def=${def}" abc=; def=abc # V $ unset def # ^ $ echo "abc=${abc}; def=${def}" abc=; def=
しかし、少し複雑かもしれません。
unix&linux
:unset
それは何をしますか?。
[2]: また参照stackoverflow
:特殊ドル記号シェル変数は何ですか?
[3]: このトピックの良いトピック: