How do I tar a directory of files and folders without including the directory itself?

前端 未结 18 656
孤城傲影
孤城傲影 2021-01-29 17:04

I typically do:

tar -czvf my_directory.tar.gz my_directory

What if I just want to include everything (including any hidden system files) in my_

相关标签:
18条回答
  • 2021-01-29 17:33

    Use the -C switch of tar:

    tar -czvf my_directory.tar.gz -C my_directory .
    

    The -C my_directory tells tar to change the current directory to my_directory, and then . means "add the entire current directory" (including hidden files and sub-directories).

    Make sure you do -C my_directory before you do . or else you'll get the files in the current directory.

    0 讨论(0)
  • 2021-01-29 17:38

    Have a look at --transform/--xform, it gives you the opportunity to massage the file name as the file is added to the archive:

    % 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
    

    Transform expression is similar to that of sed, and we can use separators other than / (, in the above example).
    https://www.gnu.org/software/tar/manual/html_section/tar_52.html

    0 讨论(0)
  • 2021-01-29 17:39
    cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd - 
    

    should do the job in one line. It works well for hidden files as well. "*" doesn't expand hidden files by path name expansion at least in bash. Below is my experiment:

    $ 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
    
    0 讨论(0)
  • 2021-01-29 17:39

    Command

    find my_directory/ -maxdepth 1 -printf "%P\n" | tar -cvf my_archive.tar -C my_directory/ -T -

    This creates a standard archive file. Standard in a way that files and dirs you want to pack are in the root of the archive. There are no extra special files as '.' and dirs as ./ before each './file'.
    Trying so many solutions which are already here with only one successfully, seems to me that using find or possibly other commands like ls -A -1 on the left side of the pipe (-1 as 'one', not -l as 'L') is the only way to achieve above goal.

    If tar file is further processed, or delivered to someone as a product of my work, then I don't want to have some weirdness there.

    Arguments description

    -maxdepth 1
    Descend at most 1 level - No recursing.
    -printf
    print format on the standard output
    %P File's name with the name of the starting-point under which it was found removed.
    \n Newline
    printf does not add a newline at the end of the string. It must be added here

    tar:
    -C DIR, --directory=DIR
    change to directory DIR

    -T FILE, --files-from=FILE
    get names to extract or create from FILE
    -
    that FILE from above is the standard input, from the pipe


    Comments on other solutions.

    The same result might be achieved using solution described by @aross.
    The difference with the solution here is in that which tool is doing the recursing. If you leave the job to find, every filepath name, goes through the pipe. It also sends all directory names, which tar with --no-recursion ignores or adds as empty ones followed by all files in each directory. If there was unexpected output as errors in file read from find, tar would not know or care what's going on.
    But with further checks, like processing error stream from find, it might be a good solution where many options and filters on files are required.
    I prefer to leave the recursing on tar, it does seem simpler and as such more stable solution.
    With my complicated directory structure, I feel more confident the archive is complete when tar will not report an error.

    Another solution using find proposed by @serendrewpity seems to be fine, but it fails on filenames with spaces. Difference is that output from find supplied by $() sub-shell is space-divided. It might be possible to add quotes using printf, but it would further complicate the statement.

    There is no reason to cd into the my_directory and then back, while using ../my_archive.tar for tar path, because TAR has -C DIR, --directory=DIR command which is there just for this purpose.

    Using . (dot) will include dots

    Using * will let shell supply the input file list. It might be possible using shell options to include dot files. But it's complicated. The command must be executed in shell which allows that. Enabling and disabling must be done before and after tar command. And it will fail if root dir of future archive contains too many files.

    That last point also applies to all those solutions which are not using pipe.

    Most of solutions are creating a dir inside which are the files and dirs. That is barely ever desired.

    0 讨论(0)
  • 2021-01-29 17:41
    cd my_directory
    tar zcvf ../my_directory.tar.gz *
    
    0 讨论(0)
  • 2021-01-29 17:41

    If it's a Unix/Linux system, and you care about hidden files (which will be missed by *), you need to do:

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

    I don't know what hidden files look like under Windows.

    0 讨论(0)
提交回复
热议问题