Open7

採用情報に載ってた謎のシェルスクリプトmvallを読み解く

leviosa42leviosa42

就活してたら謎のシェルスクリプトを発見したから読む。
現場エンジニアの自己紹介にシェルスクリプトを載せる企業ってあるんだ(すごい)

例のサイト

載ってたのがコレ。
「エディタで複数ファイル名を一括で変換できるmvall コマンド」らしい。
矩形選択ができるエディタ(つまりVimか)と相性がいいらしい。自称へっぽこVimmerとして気になる

mvall.sh
#!/bin/bash
set -eu
old=`mktemp`
new=`mktemp`
ls -1 $@ | tee $old > $new
${EDITOR:-vi} $new
[[ `wc -l < $old` -ne `wc -l < $new` ]] && exit -1
paste $old $new | while read line; do
[[ `cut -f1 <<<$line` != `cut -f2 <<<$line` ]] && mv -nv $line
done
rm -f $old $new
leviosa42leviosa42

処理の意味的なまとまりごとに分割する。
いまのところ<<<の部分がよく分かってない。<<はヒアドキュメントで<はリダイレクトだっけ?<3つ連なっている謎の記号がある...

mvall.sh
#!/bin/bash
set -eu

old=`mktemp`
new=`mktemp`

ls -1 $@ | tee $old > $new

${EDITOR:-vi} $new

[[ `wc -l < $old` -ne `wc -l < $new` ]] && exit -1

paste $old $new | while read line; do
[[ `cut -f1 <<<$line` != `cut -f2 <<<$line` ]] && mv -nv $line
done

rm -f $old $new
leviosa42leviosa42

line 1-2: shebangと実行オプション?

line 1-2
#!/bin/bash
set -eu

#!/bin/bash はshebangだから、

$ ./mvall.sh # こんな感じにファイルを直接実行をすると
$ /bin/bash ./mvall.sh # カーネル側ではこう解釈して実行してくれる

set -eu は実行時のエラーに対しての挙動を変えてたはず...

-e

-e    When this option is on, when any command fails (for any of the reasons listed in Section 2.8.1, Consequences of Shell Errors or by returning  an  exit
             status  greater than zero), the shell immediately shall exit, as if by executing the exit special built-in utility with no arguments, with the follow‐
             ing exceptions:

エラーがあったら(終了ステータスが0以外なら)exitしてくれるらしい。大事。

-u

       -u    When the shell tries to expand an unset parameter other than the '@' and '*' special parameters, it shall write a message to standard  error  and  the
             expansion shall fail with the consequences specified in Section 2.8.1, Consequences of Shell Errors.

($@$* 以外で)未定義の変数を展開しようとしたときにエラーを吐いてくれるらしい。

leviosa42leviosa42

おまけ。

-oオプションの記載に「errexit Equivalent to -e.」とか「nounset Equivalent to -u.」とかが書いてあった。
多分、-eerr exit が由来で、-uはnounset 由来?なのかなあ

man set -o
       -o option
             This option is supported if the system supports the User Portability Utilities option. It shall set various options, many of which shall be equivalent
             to the single option letters. The following values of option shall be supported:

             allexport Equivalent to -a.

             errexit   Equivalent to -e.

             ignoreeof Prevent an interactive shell from exiting on end-of-file. This setting prevents accidental logouts when <control>‐D is entered. A user shall
                       explicitly exit to leave the interactive shell.

             monitor   Equivalent to -m.  This option is supported if the system supports the User Portability Utilities option.

             noclobber Equivalent to -C (uppercase C).

             noglob    Equivalent to -f.

             noexec    Equivalent to -n.

             nolog     Prevent the entry of function definitions into the command history; see Command History List.

             notify    Equivalent to -b.

             nounset   Equivalent to -u.

             verbose   Equivalent to -v.

             vi        Allow  shell  command line editing using the built-in vi editor. Enabling vi mode shall disable any other command line editing mode provided
                       as an implementation extension.

                       It need not be possible to set vi mode on for certain block-mode terminals.

             xtrace    Equivalent to -x.

set -o hoge でも設定できることを確認。

$ cat a.sh
set -o | grep errexit
set -o errexit
set -o | grep errexit

set -o | grep nounset
set -o nounset
set -o | grep nounset

$ bash a.sh
errexit         off
errexit         on
nounset         off
nounset         on

複数オプションを指定するときはset -o opt1 -o opt2と書く。set -o opt1 opt2 だとopt1だけonになる

$ cat b.sh
set -o | grep errexit
set -o | grep nounset
set -o errexit -o nounset
set -o | grep errexit
set -o | grep nounset
$ bash b.sh
errexit         off
nounset         off
errexit         on
nounset         on
leviosa42leviosa42

おまけ2。普通にset --helpに各オプションの簡単な説明が載ってた...

  • -e ... Exit immediately if a command exits with a non-zero status.
  • -u ... Treat unset variables as an error when substituting.

おまけ1の箇所含めdiffっぽくハイライトしておいた

`set --help`
sh
set: set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...]
    Set or unset values of shell options and positional parameters.

    Change the value of shell attributes and positional parameters, or
    display the names and values of shell variables.

    Options:
      -a  Mark variables which are modified or created for export.
      -b  Notify of job termination immediately.
+      -e  Exit immediately if a command exits with a non-zero status.
      -f  Disable file name generation (globbing).
      -h  Remember the location of commands as they are looked up.
      -k  All assignment arguments are placed in the environment for a
          command, not just those that precede the command name.
      -m  Job control is enabled.
      -n  Read commands but do not execute them.
      -o option-name
          Set the variable corresponding to option-name:
              allexport    same as -a
              braceexpand  same as -B
              emacs        use an emacs-style line editing interface
+              errexit      same as -e
              errtrace     same as -E
              functrace    same as -T
              hashall      same as -h
              histexpand   same as -H
              history      enable command history
              ignoreeof    the shell will not exit upon reading EOF
              interactive-comments
                           allow comments to appear in interactive commands
              keyword      same as -k
              monitor      same as -m
              noclobber    same as -C
              noexec       same as -n
              noglob       same as -f
              nolog        currently accepted but ignored
              notify       same as -b
+              nounset      same as -u
              onecmd       same as -t
              physical     same as -P
              pipefail     the return value of a pipeline is the status of
                           the last command to exit with a non-zero status,
                           or zero if no command exited with a non-zero status
              posix        change the behavior of bash where the default
                           operation differs from the Posix standard to
                           match the standard
              privileged   same as -p
              verbose      same as -v
              vi           use a vi-style line editing interface
              xtrace       same as -x
      -p  Turned on whenever the real and effective user ids do not match.
          Disables processing of the $ENV file and importing of shell
          functions.  Turning this option off causes the effective uid and
          gid to be set to the real uid and gid.
      -t  Exit after reading and executing one command.
+      -u  Treat unset variables as an error when substituting.
      -v  Print shell input lines as they are read.
      -x  Print commands and their arguments as they are executed.
      -B  the shell will perform brace expansion
      -C  If set, disallow existing regular files to be overwritten
          by redirection of output.
      -E  If set, the ERR trap is inherited by shell functions.
      -H  Enable ! style history substitution.  This flag is on
          by default when the shell is interactive.
      -P  If set, do not resolve symbolic links when executing commands
          such as cd which change the current directory.
      -T  If set, the DEBUG and RETURN traps are inherited by shell functions.
      --  Assign any remaining arguments to the positional parameters.
          If there are no remaining arguments, the positional parameters
          are unset.
      -   Assign any remaining arguments to the positional parameters.
          The -x and -v options are turned off.

    Using + rather than - causes these flags to be turned off.  The
    flags can also be used upon invocation of the shell.  The current
    set of flags may be found in $-.  The remaining n ARGs are positional
    parameters and are assigned, in order, to $1, $2, .. $n.  If no
    ARGs are given, all shell variables are printed.

    Exit Status:
    Returns success unless an invalid option is given.
leviosa42leviosa42

line 3-4: mktemp

line 3-4
old=`mktemp`
new=`mktemp`

$old$newに一時ファイルのパスを代入してる。$(cmd)でも同じ。

leviosa42leviosa42

line 5

line 5
ls -1 $@ | tee $old > $new

ls -1 $@-1 は1行に1ファイルだけ表示するオプション。

$@はシェルスクリプトまたは関数の実行時に与えられた引数を展開するヤツ。

ls -1 $@
$ ls
a.txt b.txt c.txt
$ cat hoge.sh
ls -1 $@
$ bash hoge.sh a.txt b.txt
a.txt
b.txt