やまものブログ

メモ書きブログです (^_^;A

名称に「\」を含むファイルのディレクトリ展開・移動 〜 Windows 系の OS で作られた lzh アーカイブの解凍

Windows で作成されたと思われる lzh ファイルを展開することになりました。

まず、lzh ファイル用のアーカイバをインストールしました。
参考にしたのは
UbuntuTips/FileHandling/OpenLhaFile
です。
$ sudo apt-get install lha-sjis

これは特に問題なくインストールできました。
最低限の使い方はちょっと動作確認をしたところ以下のような感じ。

アーカイブファイルの作成(圧縮)
$ lha a <アーカイブファイル名(.lhz)> file1 ...
または
$ lha c <アーカイブファイル名(.lhz)> file1 ...

アーカイブファイルの内容一覧表示。「」は小文字のエルです
$ lha l <アーカイブファイル名(.lhz)>

アーカイブファイルの解答
$ lha x <アーカイブファイル名(.lhz)>

これで展開はできるのですが、問題がありました。
各ファイルのディレクトリ(フォルダ)の区切りが文字「\」となって、全てのファイルがベタで出力されます。例えば、下記のような名称のファイルが現れます。
dir_top\dir1\readme.txt
本来は、dir_top ディレクトリの下に dir1 ディレクトリがあり、そこに readme.txt が現れるというこのが期待する結果なのですが。

解決策として、ウェブ検索で見つけた自分に最もしっくりきたものはこちらでした。
シェルスクリプト:「ディレクトリカッター」

ここで紹介されている記述を、再帰呼出しすることで階層的に実行してみました。
      1 #!/bin/bash
      2
      3 script=${0}
      4
      5 DIRS=()
      6 for f in *\*; do
      7     if [ "${f}" = "*\*" ]; then
      8         continue
      9     fi
     10
     11     d=${f%%\*}
     12     e=${f#*\}
     13      #echo "$f"
     14     #echo "$d"
     15     #echo "$e"
     16
     17     if [ ! -d "$d" ]; then
     18         mkdir "$d"
     19         DIRS=("${DIRS[@]}" "$d")
     20     fi
     21     mv "$f" "$d/$e"
     22 done
     23
     24 for *1; do
     25     echo "${DIRS[I]}"
     26     cd "${DIRS[I]}"
     27     ${script}
     28     cd ..
     29 done

11行目と12行目
ファイル名を「\」マークで「ディレクトリ名」と「ファイル名」に分割しています。これは参考にさせてもらったサイトにあったとおりです。

18行目と19行目
ディレクトリ名」について、mkdir で作成して、DIRS 配列に登録します。

21行目
ファイルをそのディレクトリに、分割された「ファイル名」で mv します。

24~29行目
DIRS 配列に登録された各ディレクトリに移動して、本スクリプト再帰的に呼び出します。


重要な制限事項として、このスクリプトの実行では、スクリプトをフルパスで指定しなければなりません。相対パスで実行すると、27行目の再起実行において、カレントディレクトリが変更された状態となるため、正しくパスを指定できないからです。

まとめると、実行方法は以下のようになります。
その前提として
解凍したいファイル → /home/myname/download/archive1.lzh
   スクリプト  → /home/myname/bin/yenmark_directory_mover.sh
とします。
以下のような感じで実行します。
$ cd /home/myname/download
$ mkdir xxx
$ cd xxx
$ lha x ../archive1.lzh
$ /home/myname/bin/yenmark_directory_mover.sh

繰り返しますが、最終行のとおり、本スクリプトの実行はフルパスでの指定が必須です。

とりあえず、7.1 MBサイズの lzh ファイルについてエラーは無く処理できました。このファイルの概要を、Ubuntu の「アーカイブマネージャー」で確認すると、2855 個のオプジェクト(合計 10.2 MB)でした。

解凍後のファイルはこれから利用する予定なので、このスクリプトに不具合があったら、後日判明するかもしません。その際には、このページを更新します。

また、元々のファイル名に「\」マークが含まれているファイルは、正しくディレクトリ展開できないのも明らかな制限事項です。他にも予期できない問題があるかもしれません。
ですので、このスクリプトのご利用は自己責任でおねがいします

*1: I = 0; I < ${#DIRS[@]}; ++I