【自習】「第59回シェル芸勉強会」の解答例

概要

環境

次のように貧弱な作業環境ですので、Q4以降では2020.tar.bz2の代用として、入っているファイル数が10分の1である2020_mini.tar.bz2を使って解答しました。

$ neofetch
       _,met$$$$$gg.          mitsuhisa@debian
    ,g$$$$$$$$$$$$$$$P.       ----------------
  ,g$$P"     """Y$$.".        OS: Debian GNU/Linux 11 (bullseye) i686
 ,$$P'              `$$$.     Host: FMVNF40Y
',$$P       ,ggs.     `$$b:   Kernel: 5.10.0-14-686-pae
`d$$'     ,$P"'   .    $$$    Uptime: 1 hour, 41 mins
 $$P      d$'     ,    $$P    Packages: 3603 (dpkg)
 $$:      $$.   -    ,d$$'    Shell: bash 5.1.4
 $$;      Y$b._   _,d$P'      Resolution: 1280x800
 Y$$.    `.`"Y$$$$P"'         DE: Xfce 4.16
 `$$b      "-.__              WM: Xfwm4
  `Y$$                        WM Theme: Default
   `Y$$.                      Theme: HighContrast [GTK2/3]
     `$$b.                    Icons: gnome [GTK2/3]
       `Y$$b.                 CPU: Intel Celeron M 530 (1) @ 1.729GHz
          `"Y$b._             GPU: Intel Mobile 945GM/GMS, 943/940GML Express
              `"""            Memory: 493MiB / 2005MiB






Q1

先に下記コマンドでデータをダウンロード

wget https://github.com/ryuichiueda/ShellGeiData/raw/master/vol.58/nums.gz

まず、前回使ったnums.gzのデータを使い、次のようにyokoというファイルを作ってください。

zcat nums.gz | tr '\n' ' ' > yoko

yokoから、87654321番目のデータを速い方法で出力してください。

A1

$ time tr ' ' '\n' <yoko | tail -n+87654321 | head -n1
480564

real    0m3.895s
user    0m2.270s
sys     0m1.503s

Q2

nums.gzのデータについて、逆順に行番号をつけてください。様々な方法を考えて、時間を測ってみましょう。データが1億行あるという情報は使って構いません。

A2

$ time paste <(tac <(seq 100000000)) <(zcat nums.gz) >/dev/null

real    0m48.515s
user    0m25.826s
sys     0m2.205s

Q3

nums.gzのデータについて、漢数字を除去して数字順に昇順にソートしてください。展開する処理もワンライナーの中に入れてください。自身の環境で速くできる方法を考えましょう。(終わらない場合は1万〜1千万行あたりで試してみましょう。)

A3

$ time (zgrep -E '^[0-9]*$' nums.gz >/tmp/A3 && LANG=C sort -mn /tmp/A3 >/dev/null)

real    1m0.003s
user    0m52.074s
sys     0m5.141s

Q4

Q4小問1

2020.tar.bz2tar -jxvf 2020.tar.bz2で展開して2020というディレクトリに入り、最もサイズの大きいファイルを探してください。

Q4小問2

2020.tar.bz2を展開せずに最もサイズの大きいファイルを探してください。

A4

A4小問1

$ time ls -Sl | head -n2
合計 209388
-rw-r--r-- 1 mitsuhisa mitsuhisa 7967 11月  9  2020 fetch_1dXiKr0hEn3Vc5b7PAA8FsMT1iaAUz9x.cgi.20201109_103258.5744

real    0m1.609s
user    0m0.989s
sys     0m0.581s

A4小問2

$ time tar -jtvf 2020_mini.tar.bz2 | LANG=C sort -k3,3nr | head -n1
-rw-r--r-- ueda/ueda      7967 2020-11-09 10:33 2020/fetch_1dXiKr0hEn3Vc5b7PAA8FsMT1iaAUz9x.cgi.20201109_103258.5744

real    0m19.208s
user    0m16.582s
sys     0m2.068s

Q5

2020.tar.bz2tar -jxvf 2020.tar.bz2で展開して2020というディレクトリに入り、次の作業をしてください。

Q5小問1

ファイル名のhoge.cgihogeの部分に対応するディレクトリを2020の下になるべく速いワンライナーで作ってください。

Q5小問2

各ファイルを対応する名前のディレクトリに振り分けてください。最初は10000ファイルずつ移動してみましょう。

A5

A5小問1

$ time ls -f | cut -d. -f1 | sort -u | xargs mkdir

real    0m0.288s
user    0m0.174s
sys     0m0.108s
# 確認
$ find . -type d
.
./fetch_1dXiKr0hEn3Vc5b7PAA8FsMT1iaAUz9x
./full_search
./index
./key
./last_articles
./link_keywords
./rank_articles
./tagcloud

A5小問2

$ time find . -type d | sed -E 's|^./?||;s|.+|mv &.* &/|' | sh

real    0m3.420s
user    0m0.523s
sys     0m2.745s
# 確認
$ ls -1 fetch_1dXiKr0hEn3Vc5b7PAA8FsMT1iaAUz9x/
fetch_1dXiKr0hEn3Vc5b7PAA8FsMT1iaAUz9x.cgi.20200812_215032.20591
fetch_1dXiKr0hEn3Vc5b7PAA8FsMT1iaAUz9x.cgi.20200815_214913.2495
fetch_1dXiKr0hEn3Vc5b7PAA8FsMT1iaAUz9x.cgi.20201109_103258.5744
fetch_1dXiKr0hEn3Vc5b7PAA8FsMT1iaAUz9x.cgi.20201128_094948.31088
fetch_1dXiKr0hEn3Vc5b7PAA8FsMT1iaAUz9x.cgi.20201229_222407.21142

Q6

2020.tar.bz2tar -jxvf 2020.tar.bz2で展開して2020というディレクトリに入り、ログのなかで使われているコマンド(+ hoge++ hoge)の数を数え、多いものから表示してください。コマンドのふりをした変数などが混ざらないように注意してください。

A6

$ grep -Erh '^\+{1,2} [^ =]+' . | awk '{n[$2]+=1}END{for(c in n)print c"\t"n[c]}' | grep -Fv = | tr -d \' | sort -k2,2nr
sed     406091
cat     173911
date    173029
[       134083
tr      131509
cut     46355
pandoc  45615
rm      44974
set     44969
trap    44969
echo    44128
tee     43266
ls      43256
sort    6208
awk     5554
grep    5491
tac     5463
uniq    3109
head    3094
xargs   2397
nkf     2379
exit    857
read    23
cd      20
git     20
mv      20
xxd     10
cp      6
find    5
mkdir   5
tail    5
touch   5
true    4
Written on May 27, 2022