回答:
cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd -
1行で作業を行う必要があります。隠しファイルにも有効です。「*」は、少なくともbashでは、パス名の展開によって隠しファイルを展開しません。以下は私の実験です:
$ mkdir my_directory
$ touch my_directory/file1
$ touch my_directory/file2
$ touch my_directory/.hiddenfile1
$ touch my_directory/.hiddenfile2
$ cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd ..
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2
$ tar ztf my_dir.tgz
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2
.
と*
、コマンドはcd my_directory/ && tar -zcvf ../my_dir.tgz * && cd ..
期待どおりに機能します。
$ (cd my_directory/ && tar -zcvf ../my_dir.tgz .)
cd
、ディレクトリに出入りするのはかなり不十分です。少なくとも、使用時でしたpushd
し、popd
場合tar
などのいずれかのフラグを持っていませんでした-C
。
-C
tar のスイッチを使用します。
tar -czvf my_directory.tar.gz -C my_directory .
-C my_directory
現在のディレクトリを変更するにはタールを伝えmy_directory
、その後、.
(隠しファイルとサブディレクトリを含む)「全体カレントディレクトリを追加」を意味します。
実行する-C my_directory
前に必ず実行してください。そうしない.
と、現在のディレクトリにファイルが取得されます。
tar --create --file=foo.tar -C /etc passwd hosts -C /lib libc.a
」apl.jhu.edu/Misc/Unix-info/tar/tar_65.html 私はいつも試すtar -czvf my_directory.tar.gz * -C my_directory
とそれは機能しません。-C
場所は重要です!くそ
*
にワイルドカードを使用すると、隠しファイルが含まれないことに注意してください(元の要件でした)。
通常どおりアーカイブを作成し、次のコマンドで抽出することもできます。
tar --strip-components 1 -xvf my_directory.tar.gz
--strip-components
GNUの拡張です。
--transform
/を見てください。--xform
ファイルがアーカイブに追加されるときに、ファイル名をマッサージする機会が与えられます。
% mkdir my_directory
% touch my_directory/file1
% touch my_directory/file2
% touch my_directory/.hiddenfile1
% touch my_directory/.hiddenfile2
% tar -v -c -f my_dir.tgz --xform='s,my_directory/,,' $(find my_directory -type f)
my_directory/file2
my_directory/.hiddenfile1
my_directory/.hiddenfile2
my_directory/file1
% tar -t -f my_dir.tgz
file2
.hiddenfile1
.hiddenfile2
file1
変換式はの式に似ており、(上記の例では)sed
以外のセパレータを使用できます。https://www.gnu.org/software/tar/manual/html_section/tar_52.html/
,
--xform
複数のパスに複数回渡すこともできます。
find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
いくつかの条件がある場合(ファイル、dirs、symlinksのみをアーカイブ)
find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
以下は、残念ながら./
アーカイブに親ディレクトリが含まれています。
tar -czf mydir.tgz -C /my/dir .
--transform
構成オプションを使用して、そのディレクトリからすべてのファイルを移動できますが、.
ディレクトリ自体は削除されません。コマンドを飼いならすことがますます困難になります。
$(find ...)
コマンドにファイルリストを追加するために使用できます(magnusの回答のように)が、「ファイルリストが長すぎます」エラーが発生する可能性があります。最善の方法は-T
、次のようにtarのオプションと組み合わせることです。
find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
基本的には、ディレクトリの下にあるすべてのファイル(-type f
)、リンク(-type l
)、およびサブディレクトリ(-type d
)をリストし-printf "%P\n"
、を使用してすべてのファイル名を相対にし、それをtarコマンドに渡します(を使用してSTDINからファイル名を取得します-T -
)。この-C
オプションが必要なのは、相対名のファイルがどこにあるかをtarが認識できるようにするためです。--no-recursion
フラグは、タールは、それが(重複ファイルを引き起こす)アーカイブに語られているフォルダに再帰しないようにです。
ファイル名で特別なことを行う必要がある場合(フィルタリング、シンボリックリンクの追跡など)、find
コマンドは非常に強力でありtar
、上記のコマンドの一部を削除するだけでテストできます。
$ find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d
> textfile.txt
> documentation.pdf
> subfolder2
> subfolder
> subfolder/.gitignore
たとえば、PDFファイルをフィルタリングする場合は、 ! -name '*.pdf'
$ find /my/dir/ -printf "%P\n" -type f ! -name '*.pdf' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore
コマンドはprintf
(GNUで利用可能find
)を使用し、find
その結果を相対パスで出力するよう指示します。ただし、GNUがない場合find
、これはパスを相対パスにするために機能します(で親を削除しますsed
)。
find /my/dir/ -type f -o -type l -o -type d | sed s,^/my/dir/,, | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
この回答はほとんどの状況で機能します。ただし、ファイル名がとしてで./file1
はなく、たとえばtarファイルにどのように格納されているかに注意してくださいfile1
。この方法を使用して、BuildRootでパッケージファイルとして使用されているtarballを操作すると、問題が発生することがわかりました。
1つの解決策は、いくつかのBashグロブを使用して、次の..
ようなものを除くすべてのファイルをリストすることです。
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
これは私がこの答えから学んだトリックです。
今すぐ一致するファイルがない場合はtarはエラーを返します..?*
かは.[^.]*
、それはまだ動作します。エラーが問題である場合(スクリプトで成功を確認している場合)、これは機能します。
shopt -s nullglob
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
shopt -u nullglob
今はシェルオプションをいじっていますが、*
隠しファイルを一致させるのはもっといいと思うかもしれません:
shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob
これは*
、現在のディレクトリのシェルグロブでは機能しない可能性があるため、代わりに次を使用します。
shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob
tar: start.sh: Cannot stat: No such file or directory
これを行うと奇妙なエラーが発生しますこれは現在のディレクトリ内のすべてのファイルで発生します!どうすればこれを回避できますか?
私は次のBash関数を提案します(最初の引数はdirへのパス、2番目の引数は結果のアーカイブのベース名です):
function tar_dir_contents ()
{
local DIRPATH="$1"
local TARARCH="$2.tar.gz"
local ORGIFS="$IFS"
IFS=$'\n'
tar -C "$DIRPATH" -czf "$TARARCH" $( ls -a "$DIRPATH" | grep -v '\(^\.$\)\|\(^\.\.$\)' )
IFS="$ORGIFS"
}
次のように実行できます。
$ tar_dir_contents /path/to/some/dir my_archive
my_archive.tar.gz
現在のディレクトリ内にアーカイブを生成します。これは、非表示(。*)要素およびファイル名にスペースが含まれる要素で機能します。
これが私にとってうまくいきます。
tar -cvf my_dir.tar.gz -C /my_dir/ $(find /my_dir/ -maxdepth 1 -printf '%P ')
あなたも使うことができます
tar -cvf my_dir.tar.gz -C /my_dir/ $(find /my_dir/ -mindepth 1 -maxdepth 1 -printf '%P ')
最初のコマンドで、findはmy_dirのファイルとサブディレクトリのリストを返します。ただし、ディレクトリmy_dir自体はそのリストに「。」として含まれています。-printfパラメータは、その含む完全なパスを削除します「」そしてまた、すべてcrlf しかし スペースprintfのフォーマット文字列'%P'は、my_dirのファイルおよびサブディレクトリのリストに残りを残し、検索結果の先頭のスペースで確認できますコマンドの。
これはTARの問題ではありませんが、これを修正したい場合は、2番目のコマンドのように-mindepth 1を追加します。
paxを使用します。
Paxは廃止されたパッケージですが、完全にそして単純な方法で仕事をします。
pax -w > mydir.tar mydir
# tar all files within and deeper in a given directory
# with no prefixes ( neither <directory>/ nor ./ )
# parameters: <source directory> <target archive file>
function tar_all_in_dir {
{ cd "$1" && find -type f -print0; } \
| cut --zero-terminated --characters=3- \
| tar --create --file="$2" --directory="$1" --null --files-from=-
}
スペースやその他の特殊文字を含むファイル名を安全に処理します。オプションで、-name '*.sql'
類似のフィルターをfindコマンドに追加して、含まれるファイルを制限できます。
tar -cvzf tarlearn.tar.gz --remove-files mytemp/*
フォルダーがmytempの場合、上記を適用すると、フォルダー内のすべてのファイルが圧縮されて削除されますが、そのままにされます。
tar -cvzf tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/*
除外パターンを指定し、サブフォルダーも調べないように指定することもできます
tar -czf
ですか?私の場合、それはファイルではなくディレクトリを保存するだけです。私tar
がディレクトリだけを含むとき、それはそれを含みますが、tar -czf
それはファイルを追加するだけです。