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

前端 未结 18 688
孤城傲影
孤城傲影 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:42

    TL;DR

    find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
    

    With some conditions (archive only files, dirs and 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 -
    

    Explanation

    The below unfortunately includes a parent directory ./ in the archive:

    tar -czf mydir.tgz -C /my/dir .
    

    You can move all the files out of that directory by using the --transform configuration option, but that doesn't get rid of the . directory itself. It becomes increasingly difficult to tame the command.

    You could use $(find ...) to add a file list to the command (like in magnus' answer), but that potentially causes a "file list too long" error. The best way is to combine it with tar's -T option, like this:

    find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
    

    Basically what it does is list all files (-type f), links (-type l) and subdirectories (-type d) under your directory, make all filenames relative using -printf "%P\n", and then pass that to the tar command (it takes filenames from STDIN using -T -). The -C option is needed so tar knows where the files with relative names are located. The --no-recursion flag is so that tar doesn't recurse into folders it is told to archive (causing duplicate files).

    If you need to do something special with filenames (filtering, following symlinks etc), the find command is pretty powerful, and you can test it by just removing the tar part of the above command:

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

    For example if you want to filter PDF files, add ! -name '*.pdf'

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

    Non-GNU find

    The command uses printf (available in GNU find) which tells find to print its results with relative paths. However, if you don't have GNU find, this works to make the paths relative (removes parents with 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 -
    

提交回复
热议问题