2

Based on this, to tar all hidden files in the current directory one can use

ls -A | egrep '^\.' | tar cvf ./test.tar -T -

However, how can one tar only all hidden directories or all hidden directories and files in the current directory?

Based on this, ls -ap | egrep "^\..*/$" | tar -zcvf hiddens.tar.gz -T - should do the trick. Yet it does not. This command simply creates an empty tar.gz archive. So tar does not see any directories at all then by this command.

4

It is often discouraged to use ls in shellscripts or complicated command lines because the results may be difficult to predict.

The following commands using find should work, when your current directory is your home directory, ~,

cd ~

This command will only get the hidden files

LC_ALL=C find -mindepth 1 -maxdepth 1 -type f -name '.*' -print0 | tar --null -cvzf hidden-files.tar.gz -T -

This command will 'only' get the hidden directory trees (including subdirectories and files)

LC_ALL=C find -mindepth 1 -maxdepth 1 -type d -name '.*' -print0 | tar --null -cvzf hidden-dirs.tar.gz -T -

Please notice that there might be unexpected results if you have symbolic links in the directory trees.

8
  • 1
    Parsing the output of find -print is discouraged for the same reason parsing the output of ls is discouraged: it's not post-processable reliably. The output of find -print0 is post-processable reliably. Nov 8 '21 at 10:36
  • @StéphaneChazelas, should I add the option -print0 into the commands? Or should I simply delete the answer because it is better that bash users learn to use shopt -s dotglob failglob ?
    – sudodus
    Nov 8 '21 at 10:45
  • 1
    It's useful as it works even for large list of files and is likely more efficient. But yes, please change to use -print0 (and corresponding tar option bearing in mind that like -T, that won't be a portable option). Nov 8 '21 at 10:59
  • 1
    ``-exec +` wouldn't work properly if find ends up running tar several times because the list of files is big. Nov 8 '21 at 10:59
  • 1
    @sudodus, while for interactive use the bash (or zsh) way is usually preferred, many systems default to lighter-weight shells for /bin/sh that are faster, so there is value in knowing the plain POSIX (almost; -print0 is not POSIX, but should work basically everywhere it matters) way when writing scripts.
    – Jan Hudec
    Nov 8 '21 at 16:16
3

In zsh, to tar all hidden dirs (and their contents):

tar zcf file.tar.gz .*(/)

(note that the standard .*/ is not the same as zsh's .*(/) as it would also include symlinks and with some tar implementations, because a / is appended to the paths resulting from the glob expansion, would tar them as directories (along with all their contents), not symlinks, so likely not what you want; see also the note below about . and .. in many shells).

To tar hidden dirs and regular files:

tar zcf file.tar.gz .*(/,.)

To tar all hidden files regardless of their type (dirs, regular, symlinks, fifos...)

tar zcf file.tar.gz .*

That one would also work with the fish shell, or mksh or other shells based on the Forsyth shell, but not with most other shells as those other shells do include . and .. in the expansion of that glob.

With ksh93 however, you can do:

(FIGNORE='@(.|..)'; tar zcf file.tar.gz .*)

With bash:

(shopt -s dotglob failglob; tar zcf file.tar.gz [.]*)
1
  • +1; It is worthwhile for bash users to learn how to use anonther shell or shopt -s dotglob failglob to make this task simple and reliable (and probably several other tasks too).
    – sudodus
    Nov 8 '21 at 11:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.