web-dev-qa-db-ja.com

shellcheckはbasenameを使用しないようにアドバイスしています:なぜですか?

私は試しています shellcheck

私はそのようなものを持っています

basename "${OPENSSL}" 

そして私は次の提案を得る

Use parameter expansion instead, such as ${var##*/}.

実用的な観点から見ると、違いはありません

$ export OPENSSL=/opt/local/bin/openssl
$ basename ${OPENSSL}
openssl
$ echo ${OPENSSL##*/}
openssl

basenamePOSIX仕様 に含まれているため、ベストプラクティスである必要がある理由はありません。ヒントはありますか?

25
Matteo

それは効率ではなく、正確さです。 basenameは、改行を使用して、出力するファイル名を区切ります。通常、ファイル名を1つだけ渡すと、出力に末尾の改行が追加されます。ファイル名自体に改行が含まれている可能性があるため、これらのファイル名を正しく処理することは困難です。

人々が通常basenameを次のように使用するという事実により、さらに複雑になります:"$(basename "$file")"$(command)allからcommandの末尾の改行を削除するため、これはさらに困難になります。 _$file_が改行で終わるというまれなケースを考えてみましょう。次に、basenameは余分な改行を追加しますが、"$(basename "$file")"both改行を削除し、誤ったファイル名を残します。

basenameのもう1つの問題は、_$file_が_-_(ダッシュa.k.a.マイナス)で始まる場合、オプションとして解釈されることです。これは簡単に修正できます:$(basename -- "$file")

basenameを使用する堅牢な方法は次のとおりです。

_# A file with three trailing newlines.
file=$'/tmp/evil\n\n\n'

# Add an 'x' so we can tell where $file's newlines end and basename's begin.
file_x="$(basename -- "$file"; printf x)"

# Strip off two trailing characters: the 'x' added by us and the newline added by basename. 
base="${file_x%??}"
_

別の方法は_${file##*/}_を使用することです。これは簡単ですが、独自のバグがあります。特に、_$file_が_/_または_foo/_である場合は誤りです。

26
Matt

shellcheckの-​​ ソースコード の関連行は次のとおりです。

checkNeedlessCommands (T_SimpleCommand id _ (w:_)) | w `isCommand` "dirname" =
    style id "Use parameter expansion instead, such as ${var%/*}."
checkNeedlessCommands (T_SimpleCommand id _ (w:_)) | w `isCommand` "basename" =
    style id "Use parameter expansion instead, such as ${var##*/}."
checkNeedlessCommands _ = return ()

明確な説明はありませんが、関数の名前(checkNeedlessCommands)に基づいて、@ jordanmは完全に正しいように見え、新しいプロセスの分岐を回避することを示唆しています。

17
terdon

dirnamebasenamereadlinkなど(@Marcoに感謝-これは修正されています)は、セキュリティが重要になると(パスのセキュリティが必要になる)移植性の問題を引き起こす可能性があります。多くのシステム(Fedora Linuxなど)は/binに配置しますが、他のシステム(Mac OSXなど)は/usr/binに配置します。次に、WindowsにはBashがあります(例:cygwin、msysなど)。 可能な場合は、常に純粋なB​​ashを使用することをお勧めします。 (@Marcoコメントによる)

ところで、shellcheckへのポインタをありがとう、私は前にそれを見たことがありません。

3
AsymLabs