5

I wanted to move all files, including starting with dot (hidden) and folders (recursively).

So I used the following commands

shopt -s dotglob nullglob
mv ~/public/* ~/public_html/

and it worked.

But do I need to reset anything after doing shopt -s dotglob nullglob? Doesn't it change how commands like mv operate? Because I would like it changed back.

4 Answers 4

5

Yes, you would have to unset those options (with shopt -u nullglob dotglob) afterwards if you wanted the default globbing behaviour back in the current shell.

You could just do

mv ~/public/* ~/public/.* ~/public_html/

That would still generate an error without nullglob set if one of the patterns didn't match anything, obviously, but would work without having to set either option. It would probably also say something about failing to rename . since it's a directory, but that too isn't stopping it from moving the files.

A better option may be to use rsync locally:

rsync -av ~/public/ ~/public_html/

and then delete ~/public.

8
  • ~/public/* is a subset of ~/public/.*, so you only need to do mv ~/public/.* ~/public_html/
    – pileofrogs
    Jan 23, 2017 at 16:54
  • 1
    @pileofrogs That's simply not true. Try running echo .* in your home directory. Compare with echo *.
    – Kusalananda
    Jan 23, 2017 at 16:56
  • Huh. I ran ls .* before posting and saw several files without a . at the beginning. Will investigate further.
    – pileofrogs
    Jan 23, 2017 at 16:59
  • 1
    @pileofrogs Yes, those would be files in sub-directories. The directories themselves will have a . in the start of their names.
    – Kusalananda
    Jan 23, 2017 at 17:00
  • 1
    @pileofrogs You are most gracious.
    – Kusalananda
    Jan 23, 2017 at 17:03
4

Simply unset them:

shopt -u dotglob nullglob

don_crissti makes a good point that I'll elaborate on. It's not clear from the question if either dotglob or nullglob were already set before running shopt -s to set them. Thus, blindly un-setting them may not be the proper reset to do. Setting them in a subshell would leave the current shell's settings unchanged:

( shopt -s dotglob nullglob; mv ~/public/* ~/public_html/ )
1
  • nullglob makes little since here though. failglob would make more sense, but the default would work as well, you'd just get an error from mv about not being able to move the * file instead of the shell failing to match *. May 31, 2019 at 11:35
1

Here is a script that reset the option:

shopt -q dotglob && SHOPT_DOTGLOBAL=true || SHOPT_DOTGLOBAL=false
shopt -s dotglob # include hidden file
echo *
"$SHOPT_DOTGLOBAL" || shopt -u dotglob

Another way is to use shopt -p that prints commands:

SHOPT_DOTGLOBAL_RESET=$(shopt -p dotglob) || true
shopt -s dotglob # include hidden file
echo *
eval "${SHOPT_DOTGLOBAL_RESET}"

(shopt -p dotglob would return with a non-zero exit status if the option was not set which would cause the shell to exit if the errexit option was on, hence the || true to guard against it).

0
0

Any changes made by shopt will only affect the shell you're running when you run the command. IE once you close that shell, the change is gone. So, unless you like to keep one shell open for a long time (which some do, using screen or similar) you don't need to worry about it.

Personally, I use rsync as suggested by @Kusalananda

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.