読者です 読者をやめる 読者になる 読者になる

pockestrap

Web Programmer's memo

tar xvf hoge.tar.gz してカレントディレクトリが汚されるとつらいよね!

Linux ShellScript zsh

つらいですよね、カレントディレクトリにファイルをぶちまけるタイプの圧縮ファイル。
そんなあなたの為に、カレントディレクトリを汚さないで圧縮ファイルを展開する関数を書きました。
zsh用です。頑張って書きなおせばshでも動くかも(?)
2013/12/07 結構手を加えました。

#!/bin/zsh

# $1 => zip file
function extract() {
  local tmp_dir="$(mktemp -d)"
  local archive_file_name="$(basename "$1")"
  # /dev/null に投げてるのはchpwd対策
  local absolute_path="$(cd $(dirname $1) > /dev/null 2>&1 && pwd)/${archive_file_name}"

  while read line; do
    local s=$(echo -n $line | cut -d' ' -f1)
    if [[ ${archive_file_name} == *${s} ]] then
      local suffix=$s
      local command="$(echo $line | sed -E 's/^[.a-zA-Z0-9]+ +//')"
      break
    fi
  done < <(echo  \
'.tar.gz  tar xzvf
.tgz     tar xzvf
.tar.xz  tar Jxvf
.zip     unzip
.lzh     lha e
.tar.bz2 tar xjvf
.tbz     tar xjvf
.tar.Z   tar zxvf
.gz      gzip -dc
.bz2     bzip2 -dc
.Z       uncompress
.tar     tar xvf')

  ln -s "${absolute_path}" "${tmp_dir}/${archive_file_name}"
  (
    cd "${tmp_dir}" > /dev/null 2>&1
    ${=command} ${archive_file_name}
    rm "${archive_file_name}"
  )
  if [[ "$(ls "${tmp_dir}" | wc -l)" == '1' && "$(ls -F "${tmp_dir}" | grep '/' | wc -l)" == '1' ]]; then
    'cp' "${tmp_dir}/"* ./ -R
  else
    local d="$(basename "${archive_file_name}" "${suffix}")"
    mkdir "${d}"
    'cp' "${tmp_dir}/"* "${d}" -R
  fi
  rm -rf "${tmp_dir}"
}

これを、

$ extract nya.tar.gz

とすると、展開した時にファイルをばらまくような時はnya/以下にばらまいてくれます。便利。
勿論ディレクトリをちゃんと作って展開してくれるものは、2重にディレクトリを作ったりしません。

んで、ファイル形式を判別してるのがキモでして。

# file: ~/.zshrc
function extract()
{
(略)
}
alias -s {gz,tgz,zip,lzh,bz2,tbz,Z,tar,arj,xz}=extract

と書いてやると、

$ ./nya.tar.gz

みたいな感じで展開できちゃいます。めっちゃ便利。
これはzsh の suffix alias というもので、拡張子で対応するコマンドを呼び出すものですね。それなんてWindows
ちなみにこの関数の元は http://d.hatena.ne.jp/itchyny/20130227/1361933011 からだったりします。

このzshrcは https://github.com/pocke/dotfile にあるよーヽ( ・▽・)ノ