7zip で特定のファイル名でアーカイブに名前を付ける

7zip で特定のファイル名でアーカイブに名前を付ける

現在のディレクトリからすべてのファイルをアーカイブに追加し、追加された特定のファイル名/拡張子に従って出力ファイルに名前を付けようとしています。

基本的に、.exe 拡張子を持つファイルが追加される場合は、.exe が 1 つだけ、かつ少なくとも 1 つあると仮定して、アーカイブ名をそのファイルと同じにする必要があります。

Foo.exe -> Foo.7z

これまでのスクリプトは次のとおりです 7z a archive.7z *.* -x!*.sh

答え1

set -- *.exe一致するファイル名を*.exe位置パラメータとして保存します。一致するものがない場合、結果はシェルに依存します(この答え); POSIX シェルでは、リテラル*.exe文字列が最初の唯一の位置パラメータとして取得されます。

一致するものが 1 つだけあることが確実な場合は、何もテストする必要はありません。確実でない場合は、次の操作を行います。

  • ()$#に展開されるかどうかを確認します。1[ "$#" -eq 1 ]
  • 疑わしいファイルが存在するかどうかを確認します([ -e "$1"])。

探している名前は にあります$1Foo.exeに翻訳するにはFoo.7z取り除くexeそして7z${1%exe}7z)を加えます。

スニペットは次のようになります。

(
set -- *.exe
# here validate $# and/or $1 if necessary
7z a "${1%exe}7z" …
)

サブシェルを使用したので、setメインシェルの位置パラメータには影響しません。引用は重要


ノート:

  • このソリューションでは、ディレクトリを一致させることができます。ディレクトリもファイルである
  • 「すべてのファイルを追加」と書いて、 を使用しました*.* -x!*.sh。除外が「すべてのファイル」と矛盾していると批判するつもりはありません。ただし、問題があります。
    • -x!*.sh引用符で囲む必要があります。そうしないと、シェルは展開しません。一部のシェルは二重引用符内でも*展開するため、文字列は一重引用符で囲む必要があります。!
    • *.*Windowsでは「すべてのファイル」を意味する場合があります(少なくともいくつかのツールを使って)ですが、Linuxシェルではドットは厳密にドットと一致します。*ファイル名生成パターンは「すべてのファイル」に近いため、まだ「すべてのファイル」ではありません
  • 解決策はトクトウおそらく、ディレクトリの内容は「ランダムに」変更されないので、このソリューションは機能します。ディレクトリが静的でない場合は、一時的な名前でアーカイブを作成し、その内容を一覧表示して解析し、.exeアーカイブに何が保存されているか (保存されている場合) を調べ、最後にそれに応じてアーカイブの名前を変更する必要があります。
  • Linux のファイル名は一般に大文字と小文字が区別されることに留意してください。ファイル名を操作するツールも大文字と小文字を区別します。通常、set -- *.exeは を検出しませんFOO.EXE。一部のシェルではこの動作を調整できます (例: Bash で調査する)。その後、名前の変換中に、またはその他のバリアントを適切に処理するために をshopt -s nocaseglob使用する必要があります。${1%[eE][xX][eE]}7zEXEExe

関連情報