zipファイルで圧縮されたファイルの内容を検索します。

zipファイルで圧縮されたファイルの内容を検索します。

学校プロジェクトでは、zipファイルで圧縮されたファイルの内容を取得できるスクリプトを作成する必要があります。次のように、スクリプトに「検索文字列」と1つ以上のzipファイルを指定できます。

./searchZip.sh -s Tom ztest1.zip ztest2.zip
 Found the word 'Tom' in the following files:
  ztest1.zip : script1_q0638730_04-18-23-04-41.txt
  ztest2.zip : script2_q0638730-04-25-19-52-07.txt

私は試しましたが、2番目のパラメータをどのように提供するのかわかりません。誰でも助けることができますか?ありがとうございます!これは私のコードです。

function unzipFile()
{   
    unzip ztest1.zip -d  zipFiles
    unzip ztest2.zip -d zipFiles
    unzip ztest3.zip -d  zipFiles

}


if test -z "$1" 
then
    echo "Enter a name please "
    exit

else
    unzipFile
         echo "Found the word '$1' in the following files:"
        grep -ilR "$1" zipFiles/

fi
rm -r zipFiles/

ベストアンサー1

これはあなたのニーズに合わせて機能し、必要なものよりも意図的に強力です。

あなたが学生だと言ったので、私はあなたの質問に答えるだけでなく、getopts...を使用してコマンドラインオプションと引数を処理する方法とオプションを使用してより多くのタスクを実行する方法の非常に簡単な例を作成します。したかった。基本機能にいくつかの便利な機能を追加するように拡張されました。

-e、、、およびオプションは、一般的に使用されている他のツールで使用されているオプションと同じであるため、-vユーザーは互換性のない新しいオプションを学ぶことなく既存の知識を利用できます。-i-H-hgrep

同じ.zipファイルの複数の検索を高速化するために、スクリプトはunzip -v各ファイルの出力もキャッシュします(/var/tmp/デフォルトでは)。コマンドラインオプションを使用して、検索前または検索後(またはその両方)のキャッシュファイルを消去-cできます。-C

最後に二重引用符を使用しました。みんな変数の使用とは別に二重引用符が問題を引き起こす可能性がある特定の場合、つまりコマンドのオプション引数を保持するgrepときに引用符が付けられていない場合は、渡される引数には何も追加しませんが、二重引用符で囲まれているgrep場合は空の文字列を追加します。パラメータ。これはあなたができる非常に少数の状況の1つの例です。してはいけない変数を二重引用符で囲みます。他のすべての場合は二重引用符を使用してください。

注:G-Manが指摘したように、ただこのように引用符なしで使用するのがかなり安全な理由$IGNORECASEは、使用する前にそれを既知の安全な値に明示的に設定するためです(たとえば、スペース、アスタリスク、またはその他の問題のある文字はありません)。知る実際には異なる価値を持つことはできません。この特定の知識のために、この特定のケースについては引用できません。

${IGNORECASE:+"$IGNORECASE"}ただし、特に不明な任意の値(スクリプトにハードコードされていないコマンドラインから割り当てられた値など)が含まれている可能性がある場合は、使用する方が安全です。

ところで、空の場合は${varname:+"$varname"}何も返されません(空の文字列も同じです)。$varnameまたは$varname空でない場合は、二重引用符で囲まれた値です。

次のスクリプトを使用します。

$ ./searchzip.sh -h -e Tom file*.zip
     113  Defl:N       64  43% 2016-05-29 15:45 cf747915  a/Tom.txt
     113  Defl:N       64  43% 2016-05-29 15:45 cf747915  tomato/Tom.txt

または:

$ ./searchzip.sh -i -e Tom file*.zip
file1.zip:     113  Defl:N   64  43% 2016-05-29 15:45 cf747915  a/Tom.txt
file2.zip:     113  Defl:N   64  43% 2016-05-29 15:45 cf747915  b/tom.txt
file3.zip:     113  Defl:N   64  43% 2016-05-29 15:45 cf747915  c/tom3.txt
file4.zip:       0  Stored    0   0% 2016-05-29 15:50 00000000  tomato/
file4.zip:     113  Defl:N   64  43% 2016-05-29 15:45 cf747915  tomato/Tom.txt

または:

$ ./searchzip.sh -i -e Tom file*.zip | awk -F: '{print $1}' | sort -u
file1.zip
file2.zip
file3.zip
file4.zip

とにかくスクリプトは次のようになります。

#!/bin/bash

#set -x

# 1. define usage() function to print help
usage() { 

[ -n "$*" ] && echo "$@" $'\n' > /dev/stderr

cat > /dev/stderr <<__EOF__
Usage: $0 [-HhicC] [-d cachedir ] [-e PATTERN] [ -v PATTERN ]  zipfile...

-e   Pattern to search for
-v   Pattern to exclude from search
-i   Ignore case when searching
-H   Include .zip filenames in output (default)
-h   Suppress .zip filenames in output

-d   Directory to use for temporary listing files (default /var/tmp)
-c   Delete cache files before searching
-C   Delete cache files after searching

-h   This help message

Either -e or -v may be specified multiple times
__EOF__

exit 1;
}

# 2. set some defaults
CLEANUP=0
CLEAR=0
IGNORECASE=''
FNAMES='-H'
EXCL=''
pattern=''
exclude=''
cache_dir="/var/tmp"

# 3. process command-line options
while getopts ":s:e:v:d:CchHi" opt; do
    case "$opt" in
        s|e) pattern+="$OPTARG|" ;;  # -s is an undocumented alias for -e
          v) exclude+="$OPTARG|" ;;
          d) cache_dir="$OPTARG" ;;
          C) CLEANUP='1' ;;
          c) CLEAR='1' ;;
          h) FNAMES='-h' ;;
          H) FNAMES='-H' ;;
          i) IGNORECASE='-i' ;;
          *) usage ;;
    esac
done
shift $((OPTIND-1))

# 4. check and post-process options and their args
[ -z "$pattern" ] && usage 'ERROR: -e option is required' 

# remove trailing '|' from $pattern and $exclude
pattern="${pattern%|}"
exclude="${exclude%|}"

# 5. the main loop of the program that does all the work
for f in "$@" ; do
  if [ -e "$f" ] ; then
    cache_file="$cache_dir/$f.list"
    search_file="$cache_file.search"

    [ "$CLEAR" -eq 1 ] && rm -f "$cache_file"

    if [ ! -e "$cache_file" ] ; then
      unzip -v "$f" > "$cache_file"
    fi

    grep "$FNAMES" $IGNORECASE -E "$pattern" "$cache_file" > "$search_file"
    # safer to use ${IGNORECASE:+"$IGNORECASE"}

    if [ -z "$exclude" ] ; then
        sed -e "s/^.*$f[^:]*:/$f:/" "$search_file"
    else
        sed -e "s/^.*$f[^:]*:/$f:/" "$search_file" | 
          grep $IGNORECASE -v -E "$exclude" 
          # or use ${IGNORECASE:+"$IGNORECASE"}
    fi
    rm -f "$search_file"

    [ "$CLEANUP" -eq 1 ] && rm -f "$cache_file"
  fi
done

プログラムの基本構造は次のとおりです。

  1. usage()ヘルプメッセージを出力する関数の定義(オプションのエラーメッセージを含む)

  2. 一部の変数のデフォルト値の定義

  3. コマンドラインオプションの処理

  4. これらのオプションとその引数に必要な完全性チェックと後処理を実行します。

  5. 最後に、メインプログラムループがすべてのタスクを完了します。

これは、多くのプログラムで使用できる非常に一般的で非常に単純な構造です。

しかし、私はメインループにコメントを追加しませんでした。意味のある変数名を使用しているので重複しているようで、コメントは「foo」を実行する前の「#do foo」のようなコードのマイナーな説明にすぎません。必要に応じて、コードが説明が必要だと思われる部分について説明します。

おすすめ記事