class Bashcov::Detective
Detect shell scripts
Constants
- OTHER_BASENAMES
- Set<String>
-
Basenames of executables commonly used to
exec
other
processes, including shells
- SHELLSCRIPT_EXTENSIONS
- Set<String>
-
Filename extensions commonly used for shell scripts
- SHELL_BASENAMES
- Set<String>
-
Basenames of shell executables
Public Class Methods
Create an object that can be used for inferring whether a file is or is not a shell script. @param [String] bash_path path to a Bash interpreter
# File lib/bashcov/detective.rb, line 21 def initialize(bash_path) @bash_path = bash_path end
Public Instance Methods
Checks whether the provided file refers to a shell script by determining whether the first line is a shebang that refers to a shell executable, or whether the file has a shellscript extension and contains valid shell syntax. @param [String,Pathname] filename the name of the file to be checked @return [Boolean] whether filename
refers to a shell script @note returns false
when filename
is not readable, even if filename
indeed refers to a shell script.
# File lib/bashcov/detective.rb, line 33 def shellscript?(filename) return false unless File.exist?(filename) && File.readable?(filename) \ && File.file?(File.realpath(filename)) shellscript_shebang?(filename) || (shellscript_extension?(filename) && shellscript_syntax?(filename)) end
@param [String,Pathname] filename the name of the file to be checked @return [Boolean] whether filename
‘s extension is a valid shellscript extension
# File lib/bashcov/detective.rb, line 85 def shellscript_extension?(filename) SHELLSCRIPT_EXTENSIONS.include? File.extname(filename) end
@param [String,Pathname] filename the name of the file to be checked @return [Boolean] whether filename
‘s first line is a valid shell
shebang
@note assumes that filename
is readable and refers to a regular file
# File lib/bashcov/detective.rb, line 45 def shellscript_shebang?(filename) # Handle empty files that cause an immediate EOFError begin shebang = File.open(filename) { |f| f.readline.chomp } rescue EOFError return false end shellscript_shebang_line?(shebang) end
@param [String] shebang a line to test for shell shebang-itude @return [Boolean] whether the line is a valid shell shebang
# File lib/bashcov/detective.rb, line 58 def shellscript_shebang_line?(shebang) scanner = StringScanner.new(shebang) begin return false if scanner.scan(/#!\s*/).nil? shell = scanner.scan(/\S+/) return false if shell.nil? args = scanner.skip(/\s+/).nil? ? [] : scanner.rest.split(/\s+/) rescue ArgumentError # Handle "invalid byte sequence in UTF-8" from `StringScanner`. Can # happen when trying to read binary data (e.g. .pngs). return false end shell_basename = File.basename(shell) SHELL_BASENAMES.include?(shell_basename) || (OTHER_BASENAMES.include?(shell_basename) && args.any? { |arg| SHELL_BASENAMES.include?(File.basename(arg)) }) end
Private Instance Methods
@param [String,Pathname] filename the name of the file to be checked @return [Boolean] whether filename
‘s text matches valid shell syntax @note assumes that filename
is readable and refers to a regular file
# File lib/bashcov/detective.rb, line 94 def shellscript_syntax?(filename) system(@bash_path, "-n", filename.to_s, in: :close, out: :close, err: :close) $?.success? end