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_
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 -
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
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 -
Simplest way I found:
cd my_dir && tar -czvf ../my_dir.tar.gz *
cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..
This one worked for me and it's include all hidden files without putting all files in a root directory named "." like in tomoe's answer :
# 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=-
}
Safely handles filenames with spaces or other unusual characters. You can optionally add a -name '*.sql'
or similar filter to the find command to limit the files included.
This is what works for me.
tar -cvf my_dir.tar.gz -C /my_dir/ $(find /my_dir/ -maxdepth 1 -printf '%P ')
You could also use
tar -cvf my_dir.tar.gz -C /my_dir/ $(find /my_dir/ -mindepth 1 -maxdepth 1 -printf '%P ')
In the first command, find returns a list of files and sub-directories of my_dir. However, the directory my_dir is itself included in that list as '.' The -printf parameter removes the full path including that '.' and also all crlf However the space in the format string '%P ' of printf leaves a remnant in the list of files and sub-directories of my_dir and can be seen by a leading space in the result of the find command.
That will not be a problem for TAR but if you want to fix this, add -mindepth 1 as in the second command.
tar -cvzf tarlearn.tar.gz --remove-files mytemp/*
If the folder is mytemp then if you apply the above it will zip and remove all the files in the folder but leave it alone
tar -cvzf tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/*
You can give exclude patterns and also specify not to look into subfolders too