私は通常やる:
tar -czvf my_directory.tar.gz my_directory
My_directoryにすべてのもの(隠しファイルも含む)を含めたいだけで、ディレクトリ自体は含めたくない場合はどうなりますか?したくない:
my_directory
--- my_file
--- my_file
--- my_file
が欲しいです:
my_file
my_file
my_file
cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd -
一行で仕事をするべきです。隠しファイルに対しても同様に機能します。 "*"は少なくとも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
Tarの-C
スイッチを使用してください。
tar -czvf my_directory.tar.gz -C my_directory .
-C my_directory
は、現在のディレクトリをmy_directory
に変更するようにtarに指示します。そして.
は、「現在のディレクトリ全体を追加する」(隠しファイルとサブディレクトリを含む)という意味です。
-C my_directory
を実行する前に.
を実行してください。そうしないと、現在のディレクトリにファイルが作成されます。
通常どおりにアーカイブを作成し、それを抽出することもできます。
tar --strip-components 1 -xvf my_directory.tar.gz
--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
find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
いくつかの条件(ファイル、ディレクトリ、およびシンボリックリンクのみをアーカイブする)の場合:
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 'answer など)が、それにより「ファイルリストが長すぎます」エラーが発生する可能性があります。最善の方法は、次のようにtarの-T
オプションと組み合わせることです:
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コマンドに渡します(-T -
を使用してSTDINからファイル名を取得します)。 -C
オプションは、相対名のファイルがどこにあるかをtarが知るために必要です。 --no-recursion
フラグは、tarがアーカイブするように指示されたフォルダーに再帰しないようにするためです(重複ファイルを引き起こす)。
ファイル名で特別なことを行う必要がある場合(フィルタリング、シンボリックリンクなど)、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 -
この回答 ほとんどの場合にうまくいくはずです。ただし、ファイル名がtarファイルにどのように格納されているかに注意してください。たとえば、単なる./file1
ではなく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
cd my_directory
tar zcvf ../my_directory.tar.gz *
それがUnix/Linuxシステムで、隠しファイルを気にしている場合(*を見逃してしまうでしょう)、あなたはする必要があります:
cd my_directory
tar zcvf ../my_directory.tar.gz * .??*
隠しファイルがWindowsでどのように見えるかわかりません。
次の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
を生成します。隠しファイル(。*)およびファイル名にスペースが含まれている要素で機能します。
cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..
これは私のために働きました、そしてそれはすべてのファイルを "。"という名前のルートディレクトリに置かずにすべての隠しファイルを含みます。のように tomoe's answer :
Paxを使ってください。
Paxは廃止予定のパッケージですが、その仕事を完璧にそして単純なやり方で行います。
pax -w > mydir.tar mydir
私が見つけた最も簡単な方法:
cd my_dir && tar -czvf ../my_dir.tar.gz *
# 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'
などのフィルタを追加して、含まれるファイルを制限できます。