如何在不包含目录本身的情况下打开文件和文件夹的目录?

我通常会这样做:

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 .. 

应该做一行工作。 它也适用于隐藏文件。 “*”不会通过path名扩展至less在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通知tar将当前目录更改为my_directory ,然后. 意思是“添加整个当前目录”(包括隐藏文件和子目录)。

确保在执行之前先执行-C my_directory . 否则你会得到当前目录中的文件。

您也可以像平常一样创build存档,并将其解压缩到:

 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 

转换expression式与sed类似,我们可以使用除/ (在上面的例子中)以外的分隔符。
https://www.gnu.org/software/tar/manual/html_section/tar_52.html

这个答案应该在大多数情况下工作。 不过请注意,文件名是如何存储在tar文件中的,例如./file1而不仅仅是file1 。 我发现在使用这个方法来操作用作BuildRoot中的包文件的tarball时,会造成问题。

一个解决scheme是使用一些Bash globs列出除..之外的所有文件,如下所示:

 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 

虽然现在我们正在搞的shell选项,我们可能会决定更匹配隐藏的文件:

 shopt -s dotglob tar -C my_dir -zcvf my_dir.tar.gz * shopt -u dotglob 

这可能不适用于当前目录中的shell* ,所以也可以使用:

 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 * 

TL; DR

 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 . 

你可以通过使用--transformconfiguration选项将所有文件移出该目录,但这并不能解决问题. 目录本身。 驯服指挥变得越来越困难。

你可以使用$(find ...)来为命令添加一个文件列表(如magnus的答案 ),但这可能会导致“文件列表太长”的错误。 最好的办法是把它与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选项是需要的,所以焦油知道具有相对名称的文件所在的位置。 --no-recursion标志是这样的,tar不会recursion到被告知要归档的文件夹中(导致重复的文件)。

如果你需要做一些特殊的文件名(过滤,符号链接等), find命令是非常强大的,你可以通过删除上述命令的tar部分来testing它:

 $ 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' ! -name '*.pdf'

 $ find /my/dir/ -printf "%P\n" -type f ! -name '*.pdf' -o -type l -o -type d > textfile.txt > subfolder2 > subfolder > subfolder/.gitignore 

非GNU发现

该命令使用printf (在GNU find可用),它告诉find用相对path打印结果。 但是,如果你没有find GNU,这可以使path相对(使用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 - 

我会build议下面的Bash函数(第一个参数是目录的path,第二个参数是生成的归档的基本名称):

 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 。 它使用隐藏的(。*)元素和文件名中带有空格的元素。

使用pax。

Pax是一个不推荐使用的软件包,但能够以简单的方式完美地完成这项工作。

 pax -w > mydir.tar mydir 

如果是Unix / Linux系统,并且您关心隐藏文件(*会被忽略),则需要执行以下操作:

 cd my_directory tar zcvf ../my_directory.tar.gz * .??* 

我不知道在Windows下隐藏的文件是什么样的。

 find $TARGET_DIR -maxdepth 1 -type f -print0 \ | xargs --null --max-args 1 basename --zero \ | tar --create --file=result.tar --directory=$TARGET_DIR --null --files-from=- 

假设您不想包含任何子目录或来自任何子目录的任何文件。 安全地处理空格或其他不寻常的字符的文件名。 您可以select在find命令中添加-name '*.sql'或类似的filter来限制包含的文件。

 cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd .. 

这个为我工作,它包括所有隐藏的文件,没有把所有的文件放在名为“。”的根目录中。 就像在tomoe的回答中一样 :

最简单的方法,我发现:

cd my_dir && tar -czvf ../my_dir.tar.gz *

  tar -cvzf tarlearn.tar.gz --remove-files mytemp/* 

如果该文件夹是mytemp,那么如果你应用上面它将压缩和删除文件夹中的所有文件,但保持独立

  tar -cvzf tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/* 

您可以提供排除模式,也可以指定不要查看子文件夹

 tar -C my_dir -zcvf my_dir.tar.gz `ls my_dir`