2016年12月25日、一応世間ではクリスマスなのだが新宿でシェル芸勉強会があったので行ってきた。 で、その復習。

今回はエクシェル芸…というより、Excelに限らずMSオフィスのファイルをbash上でいろいろといじるという内容。 問題及び模範解答はこちら。 最初に、問題に利用するファイルをgitで落としておくといいだろう。

git clone https://github.com/ryuichiueda/ShellGeiData.git

Q1.

.xlsxや.docx、.pptxはzipファイルになっており、xlsなどのようにバイナリ形式のデータにはなっていない。 このため、unzipで展開してから再度zip化してやることで、また開けることを確認しようという問題。 問題というか、ファイルの構造を理解するのが主となっている。

とりあえず、xlsxファイルについて展開してみよう。

大体こんな感じの構造になっている。 ファイル名から、どのファイルがSheetに当たるのかは推測が立つだろう。 Excelの各シートはxmlで定義されているという事がわかる。

blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -od hanshin hanshin.xlsx 
Archive:  hanshin.xlsx
  inflating: hanshin/[Content_Types].xml  
  inflating: hanshin/_rels/.rels     
  inflating: hanshin/xl/_rels/workbook.xml.rels  
  inflating: hanshin/xl/workbook.xml  
  inflating: hanshin/xl/sharedStrings.xml  
  inflating: hanshin/xl/theme/theme1.xml  
  inflating: hanshin/xl/styles.xml   
  inflating: hanshin/xl/worksheets/sheet1.xml  
 extracting: hanshin/docProps/thumbnail.jpeg  
  inflating: hanshin/docProps/core.xml  
  inflating: hanshin/docProps/app.xml  
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ tree hanshin
hanshin
├── [Content_Types].xml
├── _rels
├── docProps
│   ├── app.xml
│   ├── core.xml
│   └── thumbnail.jpeg
└── xl
    ├── _rels
    │   └── workbook.xml.rels
    ├── sharedStrings.xml
    ├── styles.xml
    ├── theme
    │   └── theme1.xml
    ├── workbook.xml
    └── worksheets
        └── sheet1.xml

6 directories, 10 files

同様に、docx・pptxファイルについても展開してみる。

20141019OSC_LT.pptx  certificate.docx     graph.xlsx           hanshin/             hanshin.xlsx         template.pptx
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -od certificate{,.docx}
Archive:  certificate.docx
  inflating: certificate/[Content_Types].xml  
  inflating: certificate/_rels/.rels  
  inflating: certificate/word/_rels/document.xml.rels  
  inflating: certificate/word/document.xml  
  inflating: certificate/word/footnotes.xml  
  inflating: certificate/word/endnotes.xml  
  inflating: certificate/word/header1.xml  
  inflating: certificate/word/_rels/header1.xml.rels  
  inflating: certificate/word/theme/theme1.xml  
 extracting: certificate/docProps/thumbnail.jpeg  
 extracting: certificate/word/media/image1.png  
  inflating: certificate/word/_rels/settings.xml.rels  
  inflating: certificate/word/settings.xml  
  inflating: certificate/word/stylesWithEffects.xml  
  inflating: certificate/word/webSettings.xml  
  inflating: certificate/word/styles.xml  
  inflating: certificate/docProps/app.xml  
  inflating: certificate/docProps/core.xml  
  inflating: certificate/word/fontTable.xml  
  inflating: certificate/docProps/custom.xml  
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ tree certificate
certificate
├── [Content_Types].xml
├── _rels
├── docProps
│   ├── app.xml
│   ├── core.xml
│   ├── custom.xml
│   └── thumbnail.jpeg
└── word
    ├── _rels
    │   ├── document.xml.rels
    │   ├── header1.xml.rels
    │   └── settings.xml.rels
    ├── document.xml
    ├── endnotes.xml
    ├── fontTable.xml
    ├── footnotes.xml
    ├── header1.xml
    ├── media
    │   └── image1.png
    ├── settings.xml
    ├── styles.xml
    ├── stylesWithEffects.xml
    ├── theme
    │   └── theme1.xml
    └── webSettings.xml

6 directories, 19 files
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -od 20141019OSC_LT{,.pptx}
Archive:  20141019OSC_LT.pptx
  inflating: 20141019OSC_LT/[Content_Types].xml  
  inflating: 20141019OSC_LT/_rels/.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide10.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide11.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide12.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide14.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide9.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide15.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide16.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide13.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide8.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide7.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide1.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide2.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide3.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide4.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide5.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide6.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide17.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide18.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide19.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide29.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide30.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide31.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide32.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide33.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide34.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide28.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide27.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide26.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide20.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide21.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide22.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide23.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide24.xml.rels  
  inflating: 20141019OSC_LT/ppt/slides/_rels/slide25.xml.rels  
  inflating: 20141019OSC_LT/ppt/_rels/presentation.xml.rels  
  inflating: 20141019OSC_LT/ppt/presentation.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide25.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide21.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide20.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide19.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide18.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide17.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide16.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide15.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide14.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide13.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide22.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide23.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide34.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide26.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide27.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide28.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide29.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide30.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide31.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide32.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide33.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide12.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide11.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide10.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide1.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide2.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide3.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide4.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide24.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide6.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide9.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide5.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide7.xml  
  inflating: 20141019OSC_LT/ppt/slides/slide8.xml  
  inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout2.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout9.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout10.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout11.xml.rels  
  inflating: 20141019OSC_LT/ppt/notesSlides/_rels/notesSlide1.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout8.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout7.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout6.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout5.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout4.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout3.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout1.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideMasters/slideMaster1.xml  
  inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout1.xml  
  inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout8.xml  
  inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout9.xml  
  inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout10.xml  
  inflating: 20141019OSC_LT/ppt/slideMasters/_rels/slideMaster1.xml.rels  
  inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout7.xml  
  inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout6.xml  
  inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout5.xml  
  inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout4.xml  
  inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout3.xml  
  inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout2.xml  
  inflating: 20141019OSC_LT/ppt/notesSlides/notesSlide1.xml  
  inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout11.xml  
 extracting: 20141019OSC_LT/ppt/media/image2.gif  
  inflating: 20141019OSC_LT/ppt/handoutMasters/_rels/handoutMaster1.xml.rels  
 extracting: 20141019OSC_LT/ppt/media/image3.png  
 extracting: 20141019OSC_LT/ppt/media/image10.jpg  
 extracting: 20141019OSC_LT/docProps/thumbnail.jpeg  
  inflating: 20141019OSC_LT/ppt/handoutMasters/handoutMaster1.xml  
  inflating: 20141019OSC_LT/ppt/notesMasters/notesMaster1.xml  
  inflating: 20141019OSC_LT/ppt/theme/theme1.xml  
  inflating: 20141019OSC_LT/ppt/notesMasters/_rels/notesMaster1.xml.rels  
 extracting: 20141019OSC_LT/ppt/media/image9.jpg  
 extracting: 20141019OSC_LT/ppt/media/image7.png  
 extracting: 20141019OSC_LT/ppt/media/image1.png  
 extracting: 20141019OSC_LT/ppt/media/image4.png  
 extracting: 20141019OSC_LT/ppt/media/image8.jpg  
  inflating: 20141019OSC_LT/ppt/theme/theme3.xml  
  inflating: 20141019OSC_LT/ppt/theme/theme2.xml  
 extracting: 20141019OSC_LT/ppt/media/image5.png  
 extracting: 20141019OSC_LT/ppt/media/image6.gif  
  inflating: 20141019OSC_LT/ppt/viewProps.xml  
  inflating: 20141019OSC_LT/ppt/tableStyles.xml  
  inflating: 20141019OSC_LT/ppt/presProps.xml  
  inflating: 20141019OSC_LT/docProps/app.xml  
  inflating: 20141019OSC_LT/docProps/core.xml  
  inflating: 20141019OSC_LT/ppt/printerSettings/printerSettings1.bin  
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ tree 20141019OSC_LT
20141019OSC_LT
├── [Content_Types].xml
├── _rels
├── docProps
│   ├── app.xml
│   ├── core.xml
│   └── thumbnail.jpeg
└── ppt
    ├── _rels
    │   └── presentation.xml.rels
    ├── handoutMasters
    │   ├── _rels
    │   │   └── handoutMaster1.xml.rels
    │   └── handoutMaster1.xml
    ├── media
    │   ├── image1.png
    │   ├── image10.jpg
    │   ├── image2.gif
    │   ├── image3.png
    │   ├── image4.png
    │   ├── image5.png
    │   ├── image6.gif
    │   ├── image7.png
    │   ├── image8.jpg
    │   └── image9.jpg
    ├── notesMasters
    │   ├── _rels
    │   │   └── notesMaster1.xml.rels
    │   └── notesMaster1.xml
    ├── notesSlides
    │   ├── _rels
    │   │   └── notesSlide1.xml.rels
    │   └── notesSlide1.xml
    ├── presProps.xml
    ├── presentation.xml
    ├── printerSettings
    │   └── printerSettings1.bin
    ├── slideLayouts
    │   ├── _rels
    │   │   ├── slideLayout1.xml.rels
    │   │   ├── slideLayout10.xml.rels
    │   │   ├── slideLayout11.xml.rels
    │   │   ├── slideLayout2.xml.rels
    │   │   ├── slideLayout3.xml.rels
    │   │   ├── slideLayout4.xml.rels
    │   │   ├── slideLayout5.xml.rels
    │   │   ├── slideLayout6.xml.rels
    │   │   ├── slideLayout7.xml.rels
    │   │   ├── slideLayout8.xml.rels
    │   │   └── slideLayout9.xml.rels
    │   ├── slideLayout1.xml
    │   ├── slideLayout10.xml
    │   ├── slideLayout11.xml
    │   ├── slideLayout2.xml
    │   ├── slideLayout3.xml
    │   ├── slideLayout4.xml
    │   ├── slideLayout5.xml
    │   ├── slideLayout6.xml
    │   ├── slideLayout7.xml
    │   ├── slideLayout8.xml
    │   └── slideLayout9.xml
    ├── slideMasters
    │   ├── _rels
    │   │   └── slideMaster1.xml.rels
    │   └── slideMaster1.xml
    ├── slides
    │   ├── _rels
    │   │   ├── slide1.xml.rels
    │   │   ├── slide10.xml.rels
    │   │   ├── slide11.xml.rels
    │   │   ├── slide12.xml.rels
    │   │   ├── slide13.xml.rels
    │   │   ├── slide14.xml.rels
    │   │   ├── slide15.xml.rels
    │   │   ├── slide16.xml.rels
    │   │   ├── slide17.xml.rels
    │   │   ├── slide18.xml.rels
    │   │   ├── slide19.xml.rels
    │   │   ├── slide2.xml.rels
    │   │   ├── slide20.xml.rels
    │   │   ├── slide21.xml.rels
    │   │   ├── slide22.xml.rels
    │   │   ├── slide23.xml.rels
    │   │   ├── slide24.xml.rels
    │   │   ├── slide25.xml.rels
    │   │   ├── slide26.xml.rels
    │   │   ├── slide27.xml.rels
    │   │   ├── slide28.xml.rels
    │   │   ├── slide29.xml.rels
    │   │   ├── slide3.xml.rels
    │   │   ├── slide30.xml.rels
    │   │   ├── slide31.xml.rels
    │   │   ├── slide32.xml.rels
    │   │   ├── slide33.xml.rels
    │   │   ├── slide34.xml.rels
    │   │   ├── slide4.xml.rels
    │   │   ├── slide5.xml.rels
    │   │   ├── slide6.xml.rels
    │   │   ├── slide7.xml.rels
    │   │   ├── slide8.xml.rels
    │   │   └── slide9.xml.rels
    │   ├── slide1.xml
    │   ├── slide10.xml
    │   ├── slide11.xml
    │   ├── slide12.xml
    │   ├── slide13.xml
    │   ├── slide14.xml
    │   ├── slide15.xml
    │   ├── slide16.xml
    │   ├── slide17.xml
    │   ├── slide18.xml
    │   ├── slide19.xml
    │   ├── slide2.xml
    │   ├── slide20.xml
    │   ├── slide21.xml
    │   ├── slide22.xml
    │   ├── slide23.xml
    │   ├── slide24.xml
    │   ├── slide25.xml
    │   ├── slide26.xml
    │   ├── slide27.xml
    │   ├── slide28.xml
    │   ├── slide29.xml
    │   ├── slide3.xml
    │   ├── slide30.xml
    │   ├── slide31.xml
    │   ├── slide32.xml
    │   ├── slide33.xml
    │   ├── slide34.xml
    │   ├── slide4.xml
    │   ├── slide5.xml
    │   ├── slide6.xml
    │   ├── slide7.xml
    │   ├── slide8.xml
    │   └── slide9.xml
    ├── tableStyles.xml
    ├── theme
    │   ├── theme1.xml
    │   ├── theme2.xml
    │   └── theme3.xml
    └── viewProps.xml

19 directories, 121 files

あとは、またzip化して開けることを確認してやれば良い。 この一連の処理をワンラインで記述する場合、以下のようになる。

ls -1 *x | awk -F. '{cmd="unzip -d "$1" "$0 ";(cd "$1";zip -r ../"$1"_2."$2" ./)";system(cmd)}'

Q2.

「20141019OSC_LT.pptx」ファイルで、何度「危険」というキーワードが出てくるかを計算する。 とりあえず、以下の内容で回答した。

unzip -p 20141019OSC_LT.pptx ppt/slides/slide*.xml | grep -o 危険 | wc -l

一応補足説明を入れておくと、unzipでは以下のようにzipファイル内で展開するファイルを指定することができる(ワイルドカード指定可能。 (複数指定できるので)ブレース展開での指定可能)

で、PowerPointの各スライドの内容だけを取得することが目的なので「ppt/slides/」配下にあるslideXX.xmlファイルのみを取得している。 また「-p」オプションで展開した内容を標準出力で出力できるので、それをそのままgrepに渡してやり数を数えている。 このとき、-cでカウントすると同じ行に複数目当ての単語がある場合1個としてカウントされてしまうので注意。

ちなみに、unzipでは「-l」でzipファイルの中身を確認できるので、先にそれで展開するファイルの推測を立てるといいだろう。

unzip -l zipファイル
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -l certificate.docx
Archive:  certificate.docx
  Length      Date    Time    Name
---------  ---------- -----   ----
     2041  1980-01-01 00:00   [Content_Types].xml
      882  1980-01-01 00:00   _rels/.rels
     1345  1980-01-01 00:00   word/_rels/document.xml.rels
    43370  1980-01-01 00:00   word/document.xml
     1635  1980-01-01 00:00   word/footnotes.xml
     1629  1980-01-01 00:00   word/endnotes.xml
     4729  1980-01-01 00:00   word/header1.xml
      289  1980-01-01 00:00   word/_rels/header1.xml.rels
     7643  1980-01-01 00:00   word/theme/theme1.xml
    45844  1980-01-01 00:00   docProps/thumbnail.jpeg
   149691  1980-01-01 00:00   word/media/image1.png
      460  1980-01-01 00:00   word/_rels/settings.xml.rels
     3811  1980-01-01 00:00   word/settings.xml
     9472  1980-01-01 00:00   word/stylesWithEffects.xml
      431  1980-01-01 00:00   word/webSettings.xml
     8606  1980-01-01 00:00   word/styles.xml
     1043  1980-01-01 00:00   docProps/app.xml
      754  1980-01-01 00:00   docProps/core.xml
     1742  1980-01-01 00:00   word/fontTable.xml
      353  1980-01-01 00:00   docProps/custom.xml
---------                     -------
   285770                     20 files

Q3.

「20141019OSC_LT.pptx」ファイルにある画像ファイルのみを抽出し別ディレクトリに移動、zip化してやろうという問題。 以下の内容で回答している。

unzip -d ./pic 20141019OSC_LT.pptx *{png,gif,jpeg,jpg};zip -r pic.zip ./pic
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -od ./pic 20141019OSC_LT.pptx *{png,gif,jpeg,jpg};zip -r pic.zip ./pic
Archive:  20141019OSC_LT.pptx
 extracting: ./pic/ppt/media/image2.gif
 extracting: ./pic/ppt/media/image3.png
 extracting: ./pic/ppt/media/image10.jpg
 extracting: ./pic/docProps/thumbnail.jpeg
 extracting: ./pic/ppt/media/image9.jpg
 extracting: ./pic/ppt/media/image7.png
 extracting: ./pic/ppt/media/image1.png
 extracting: ./pic/ppt/media/image4.png
 extracting: ./pic/ppt/media/image8.jpg
 extracting: ./pic/ppt/media/image5.png
 extracting: ./pic/ppt/media/image6.gif
updating: pic/ (stored 0%)
updating: pic/docProps/ (stored 0%)
updating: pic/docProps/thumbnail.jpeg (deflated 22%)
updating: pic/ppt/ (stored 0%)
updating: pic/ppt/media/ (stored 0%)
updating: pic/ppt/media/image6.gif (deflated 0%)
updating: pic/ppt/media/image8.jpg (deflated 7%)
updating: pic/ppt/media/image3.png (deflated 1%)
updating: pic/ppt/media/image7.png (deflated 10%)
updating: pic/ppt/media/image2.gif (deflated 1%)
updating: pic/ppt/media/image9.jpg (deflated 12%)
updating: pic/ppt/media/image5.png (deflated 13%)
updating: pic/ppt/media/image4.png (deflated 4%)
updating: pic/ppt/media/image10.jpg (deflated 6%)
updating: pic/ppt/media/image1.png (deflated 4%)
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -l pic.zip
Archive:  pic.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2016-12-26 12:05   pic/
        0  2016-12-26 12:07   pic/docProps/
    11732  1980-01-01 00:00   pic/docProps/thumbnail.jpeg
        0  2016-12-26 12:05   pic/ppt/
        0  2016-12-26 12:07   pic/ppt/media/
    67739  1980-01-01 00:00   pic/ppt/media/image6.gif
    95304  1980-01-01 00:00   pic/ppt/media/image8.jpg
    13744  1980-01-01 00:00   pic/ppt/media/image3.png
   159302  1980-01-01 00:00   pic/ppt/media/image7.png
    99260  1980-01-01 00:00   pic/ppt/media/image2.gif
   379635  1980-01-01 00:00   pic/ppt/media/image9.jpg
    70496  1980-01-01 00:00   pic/ppt/media/image5.png
   186174  1980-01-01 00:00   pic/ppt/media/image4.png
   111613  1980-01-01 00:00   pic/ppt/media/image10.jpg
   426687  1980-01-01 00:00   pic/ppt/media/image1.png
---------                     -------
  1621686                     15 files

ただ、基本的にメディアファイルはすべて「ppt/media/」配下にあるのでそこだけ指定してやってもよかったかも。 「docProps/thumbnail.jpeg」ってサムネイルだしいらないと思われる。

Q4.

「20141019OSC_LT.pptx」のスライド7ページ目のテキストをスクレイピングする、という問題。 これについては、時間内に解くことができなかった。

で、@ebanさんの回答がやっぱりすごかったので、それ+@grethlenQ4の回答を参考にしたのが以下。 (ほとんど丸パクリのような気もしなくも…?)

unzip -p 20141019OSC_LT.pptx *slide7.xml | grep -oP '(?<=<a:p>).*?(?=</a:p>)' | sed 's/<[^>]*>//g' | awk NF
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ # スライド7枚目の情報だけ出力する
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -p 20141019OSC_LT.pptx *slide7.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"><p:cSld><p:spTree><p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr><p:sp><p:nvSpPr><p:cNvPr id="2" name="タイトル 1"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="title"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>戦果(? )</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0"/></a:p></p:txBody></p:sp><p:sp><p:nvSpPr><p:cNvPr id="3" name="コンテンツ プレースホルダー 2"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph idx="1"/></p:nvPr></p:nvSpPr><p:spPr><a:xfrm><a:off x="457200" y="1599083"/><a:ext cx="8229600" cy="4708525"/></a:xfrm></p:spPr><p:txBody><a:bodyPr><a:normAutofit fontScale="92500" lnSpcReduction="10000"/></a:bodyPr><a:lstStyle/><a:p><a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>初日だけで見知らぬ方の</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>マシン</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0"/><a:t>3</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0"/><a:t>台轟沈</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/></a:p><a:p><a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0"/></a:p><a:p><a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>その他自爆者多数</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/></a:p><a:p><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/></a:p><a:p><a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" err="1" smtClean="0"/><a:t>Docker</a:t></a:r><a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>上で試したらホストマシン沈黙の報告</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/></a:p><a:p><a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0"/></a:p><a:p><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>自分の本がサイト経由で</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/><a:t>1</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>冊だけ売れた</a:t></a:r><a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/></a:p><a:p><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0"/></a:p><a:p><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>フォロワーが</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/><a:t>1</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>人減った</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0"/></a:p></p:txBody></p:sp><p:sp><p:nvSpPr><p:cNvPr id="4" name="日付プレースホルダー 3"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="dt" sz="half" idx="10"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" smtClean="0"/><a:t>2014/10/19</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/></a:p></p:txBody></p:sp><p:sp><p:nvSpPr><p:cNvPr id="5" name="フッター プレースホルダー 4"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="ftr" sz="quarter" idx="11"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" smtClean="0"/><a:t>OSC Tokyo/Fall 2014</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/></a:p></p:txBody></p:sp><p:sp><p:nvSpPr><p:cNvPr id="6" name="スライド番号プレースホルダー 5"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="sldNum" sz="quarter" idx="12"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:fld id="{14601655-C245-0940-ADDB-4E06ABBCA83C}" type="slidenum"><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" smtClean="0"/><a:t>7</a:t></a:fld><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/></a:p></p:txBody></p:sp></p:spTree><p:extLst><p:ext uri="{BB962C8B-B14F-4D97-AF65-F5344CB8AC3E}"><p14:creationId xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" val="3384791587"/></p:ext></p:extLst></p:cSld><p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr><p:timing><p:tnLst><p:par><p:cTn id="1" dur="indefinite" restart="never" nodeType="tmRoot" xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main"/></p:par></p:tnLst></p:timing></p:sld>
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ # grepでPerlの肯定先読み正規表現を用いて、「<a:p>~</a:p>(1行)」ごとに抽出する
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -p 20141019OSC_LT.pptx *slide7.xml | grep -oP '(?<=<a:p>).*?(?=</a:p>)'
<a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>戦果(?)</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0"/>
<a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>初日だけで見知らぬ方の</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>マシン</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0"/><a:t>3</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0"/><a:t>台轟沈</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/>
<a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0"/>
<a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>その他自爆者多数</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/>
<a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/>
<a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" err="1" smtClean="0"/><a:t>Docker</a:t></a:r><a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>上で試したらホストマシン沈黙の報告</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/>
<a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0"/>
<a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>自分の本がサイト経由で</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/><a:t>1</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>冊だけ売れた</a:t></a:r><a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/>
<a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0"/>
<a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>フォロワーが</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/><a:t>1</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>人減った</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0"/>
<a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" smtClean="0"/><a:t>2014/10/19</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/>
<a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" smtClean="0"/><a:t>OSC Tokyo/Fall 2014</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/>
<a:fld id="{14601655-C245-0940-ADDB-4E06ABBCA83C}" type="slidenum"><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" smtClean="0"/><a:t>7</a:t></a:fld><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/>
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ # sedでタグ関係をすべて削除する
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -p 20141019OSC_LT.pptx *slide7.xml | grep -oP '(?<=<a:p>).*?(?=</a:p>)' | sed 's/<[^>]*>//g'
戦果(?)
初日だけで見知らぬ方のマシン3台轟沈

その他自爆者多数

Docker上で試したらホストマシン沈黙の報告

自分の本がサイト経由で1冊だけ売れた

フォロワーが1人減った
2014/10/19
OSC Tokyo/Fall 2014
7
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ # 空白行を削除する
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -p 20141019OSC_LT.pptx *slide7.xml | grep -oP '(?<=<a:p>).*?(?=</a:p>)' | sed 's/<[^>]*>//g' | awk NF
戦果(?)
初日だけで見知らぬ方のマシン3台轟沈
その他自爆者多数
Docker上で試したらホストマシン沈黙の報告
自分の本がサイト経由で1冊だけ売れた
フォロワーが1人減った
2014/10/19
OSC Tokyo/Fall 2014
7

Q5.

「graph.xlsx」の内容を、SSV(スペース区切り)の形式で取得するという内容。 とりあえず、最も楽なxlsx2csvで回答した。

xlsx2csv -d' ' graph.xlsx
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ xlsx2csv -d' ' graph.xlsx
0 -5
0.5 -7.375
1 -14
1.5 -24.125
2 -37
2.5 -51.875
3 -68
3.5 -84.625
4 -101
4.5 -116.375
5 -130
5.5 -141.125
6 -149
6.5 -152.875
7 -152
7.5 -145.625
8 -133
8.5 -113.375
9 -86
9.5 -50.125
10 -5
10.5 50.125
11 116

xlsx2csvを使わない場合は @grethlenこちらの回答が参考になる。

Q6.

「hanshin.xlsx」について、Q5と同様にSSV形式にするという問題。 こちらも、地味にxlsx2csvを使えばいい感じにやってくれはする。

xlsx2csv -d' ' hanshin.xlsx
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ xlsx2csv -d' ' hanshin.xlsx
 42522 42561
1 真弓 真弓
2 弘田 北村
3 バース バース
4 掛布 掛布
5 岡田 佐野
6 佐野 木戸
7 平田 平田
8 木戸 永尾
9 ゲイル 池田

とはいえ、それだと芸が無いので日付をUNIXTIMEに変換して加工、「YYYY年MM月DD日」形式で表示させてみる。
(ちょっと長い)

xlsx2csv -d' ' hanshin.xlsx | awk 'NR==1{for(i=1;i<NF;i++){cmd="date -d @$(echo $((("$i" - 25569) * 86400))) +%Y年%m月%d日";cmd|getline t;s=s" "t;close(cmd);}print s}NR!=1{print}'
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ xlsx2csv -d' ' hanshin.xlsx | awk 'NR==1{for(i=1;i<NF;i++){cmd="date -d @$(echo $((("$i" - 25569) * 86400))) +%Y年%m月%d日";cmd|getline t;s=s" "t;close(cmd);}print s}NR!=1{print}'
 2016年06月01日 2016年07月10日
1 真弓 真弓
2 弘田 北村
3 バース バース
4 掛布 掛布
5 岡田 佐野
6 佐野 木戸
7 平田 平田
8 木戸 永尾
9 ゲイル 池田

あとxlsx2csvを使わないで回答する方法について。 Excelでは、Stringファイルについては「xl/sharedStrings.xml」に格納されているので、ここの内容をSheetのデータである「xl/worksheets/sheet1.xml」と組み合わせてやればよい。

Excelの「xl/worksheets/sheet1.xml」から「xl/sharedStrings.xml」の値の参照は データの順番(というか、0から始まるので配列のようなイメージ。なんだそりゃ…) になっている。 xlsx2csvを使わない方法で解くとなると、模範解答のように2ファイルに分けて対応するのが一般的だと思う。

Q7&Q8

Q7とQ8はほぼほぼセットになっている。 Wordの特定の文字列を置換して、list.txtにある3名分の表彰状を作成するというもの。 (Wordの場合、確か差し込み印刷ってなかったっけ…?とも思ったが、印刷じゃないので気にしない)

とりあえず、以下の内容で回答した。

cat list.txt | xargs -n 1 -I@ sh -c 'unzip -d @ certificate.docx;sed -i s/WINNER/@/g @/word/document.xml;(cd @;zip -r ../@.docx ./)'

これで、「シェル芸おじさん.docx」などのファイルができているはずだ。 作業用のディレクトリ削除については行ってないので、ホントだったら消しといたほうがいいかも?

Perlの肯定正規表現については知らなかったので、あとで調べておきたい。