14

This is a bit of an embarrassing question, but I have to admit that this late in my career I still have questions about the mv command.

I frequently have this problem: I need to move all files recursively up one level. Let's say I have folder foo, and a folder bar inside it. Bar has a mess of files and folders, including dot files and folders. How do I move everything in bar to the foo level?

If foo is empty, I simply move bar one level above, delete foo and rename bar into foo. Part of the problem is that I can't figure out what mv's wildcard for "everything including dots" is. A part of this question is this - is there an in-depth discussion of the wildcards that cp and mv commands use somewhere (googling this only brings very basic tutorials).

Dennis Williamson
  • 60,515
  • 14
  • 113
  • 148
deadprogrammer
  • 1,661
  • 7
  • 24
  • 25

6 Answers6

19

In Bash (and some others), you can use brace expansion to accomplish this in one line:

mv bar/{,.}* .

The comma separates a null and a dot, so the mv command sees filenames that match * and .*

Dennis Williamson
  • 60,515
  • 14
  • 113
  • 148
  • this attempts to move '..' too, fails with message 'resource is busy'. Works nonetheless. – Xananax Apr 02 '12 at 10:02
  • 3
    Suggested by anonymous user: `To eliminate the error caused by also matching "." and "..", use this command: mv bar/{,.[!.],..?}* .` – HopelessN00b Oct 06 '12 at 02:21
3

This one harvests all files from subfolders and moves them to current dir

find . -type f -exec mv -iv \{} . \;

If You want to owerwrite files with same name, use

yes y | find . -type f -exec mv -iv \{} . \;
michelek
  • 131
  • 2
2

The easiest way to do this is to do it in two command, because * doesn't match .whatever

cd /foo
mv bar/* ./
mv bar/.??* ./

You do not want to use bar/.* which I found out while committing this mistake:

rm -rf ./.* 

This is a BAD THING. Anyone want to guess why? ;-)

Matt Simmons
  • 20,218
  • 10
  • 67
  • 114
2

First thing to know about globbing --it's done by the shell, not the command. Check your shell's man page for all the details.

Jeff Leyser
  • 682
  • 6
  • 19
1

mv .??* * will take care of anything except dot followed by a single character. If that's common for your situation, you can add .[a-zA-Z0-9]*. That will still leave files with names such as .;, .^, and .^I (tab). If you need to handle everything, you'll need to be a bit more complex.

mv .. `ls -f | egrep -v '^.$|^..$'
mpez0
  • 1,492
  • 9
  • 9
0

If you have a directory structure /foo/bar/ and you want to move all files under bar one step above, go into the bar directory and type the following:

find . -depth -print0 | cpio --null -pvd ../

Generally, I think cpio(1) is better for these kind of tasks. You can check out the detailed documentation by issuing info cpio in your shell.

fim
  • 497
  • 2
  • 5