Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I have a directory with lots of files and directories in it. In order to tidy it up, I'm going to put all those files into a directory, so I was going to do something like this:

$ ls | wc -l
123
$ mkdir new_directory
$ mv * ./new_directory

However that obviously won't work because then it'll try to move new_directory into new_directory. Is there some simple way to do what I want in one line without me having to copy and paste all the files and directories in that directory?

share|improve this question
3  
it works, it just prints an error message that it's unable to move new_directory into itself. –  cas Sep 8 '09 at 21:49

9 Answers 9

up vote 10 down vote accepted

Your

mv * ./new_directory
command will actually work; it'll just print a warning that it can't move that directory into itself.

share|improve this answer
    
The 'only' problem with this is that if the total expansion of the command becomes too long (i.e. too many files, too long names) this will no longer work. –  Niels Basjes Sep 8 '09 at 11:22
    
As a side note, if you're going to do this with a git mv you must use the -k flag, since git will fail by default, not just spit out a warning. So you'll need to do git mv -k * ./new_dir. –  Yuval A Apr 11 '12 at 22:36

If you're just looking for the files (i.e. not directories), then

find . -type f -maxdepth 1 -exec mv {} ./new_directory/ \;

is the most portable solution. For speed, you should move find and xargs, with -print0 and -0, but only if you've got GNU find and xargs.

share|improve this answer
3  
Using a fairly recent GNU find, you could also use \+ instead of \; to decrease the number of mv's we are making. –  wzzrd Sep 8 '09 at 9:50
    
If you've got GNU find, you're as well to use xargs, which'll do the same, and let you run multiple mvs at the same time with the -p flag. –  Cian Sep 8 '09 at 9:59
    
cool use of find - though I've definitely been on systems that don't have one, sadly :( –  warren Sep 8 '09 at 10:10
    
Really? find is (afaik) specified in SUS, so everything should have it. The only issue is whether it's GNU find (which has lots of nice cool options) or regular find. –  Cian Sep 8 '09 at 10:27
    
Yep, it appears to be opengroup.org/onlinepubs/009695399/utilities/find.html –  Cian Sep 8 '09 at 10:29

A fast and dirty oneliner.

mv `ls -A | grep -v new_directory` ./new_directory
share|improve this answer
1  
Will not work: a plain ls will not show dotfiles. –  wzzrd Sep 8 '09 at 9:51
    
Very good point. Fixed that with an -a. –  Rembane Sep 8 '09 at 9:54
    
So instead of trying to mv new_directory to itself (Original question) you are now trying to move . and .. into new_directory. –  Niels Basjes Sep 8 '09 at 11:21
1  
Thanks for the feedback Niels. Fixed it with an upper a which removes the . and the .. from the directory listing. –  Rembane Sep 8 '09 at 11:30

The times that I've had this problem, I've done one of the following:

$ mkdir ../new-directory
$ mv * ../new-directory/
$ mv ../new-directory .

or

$ mkdir .new-directory
$ mv * .new-directory/
$ mv .new-directory new-directory

The second form takes advantage of the wildcard skipping filenames that start with '.'

share|improve this answer

what about:

cd ..
mv old_dir new_directory
mkdir old_dir
mv new_directory old_dir

IOW, don't move the contents into a new directory, but put this directory inside a new one.

share|improve this answer

In similar fashion to @Rembrane's answer (though not a one-liner):

for FN in *
do
    if [ "<new_dir>" != $FN ] then
        mv $FN <new_dir>
done

This should be 100% portable - even if find is sadly absent from your system.

share|improve this answer
    
find is required in the single unix spec. As such, it should never be absent (not that you couldn't build something with out it. But I'd imagine it'd require a horrendous amount of effort, and no vendor system will lack it) –  Cian Sep 8 '09 at 10:30
    
maybe it's some hyper-paranoid sysadmin yoinking findutils or its equivalent? not sure, but I know I've run into boxen that don't have it :( –  warren Sep 8 '09 at 16:15

My suggestions: As stated by others the

mv * ./new_directory

will work find IFF the total expansion is short enough.

Other wise you can try this one that scales to much much larger numbers of files:

find . -type f -maxdepth 1 | xargs -s100000 echo | xargs -iXXX mv XXX new_directory

Explanation

  1. List all files.
  2. Group all filesnames into chunks of max 100000 chars.
  3. Construct a single mv command per chunk.
share|improve this answer
    
breaks if you've got any spaces in your file names –  Cian Sep 8 '09 at 11:54
    
You're right. So i guess this should be augmented with -print0 and -0 flags to fix. –  Niels Basjes Sep 8 '09 at 12:11
    
I've tried with -print0 and -0 and it still breaks. –  Cristian Ciupitu Sep 8 '09 at 19:14
    
find: warning: you have specified the -maxdepth option after a non-option argument -type, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it). Please specify options before other arguments. –  Cristian Ciupitu Sep 8 '09 at 19:14

Use:

find -mindepth 1 -maxdepth 1 \! -name new_directory -print0 | \
	xargs -0 -P 100 -I'{}' mv '{}' new_directory

From the xargs man page:

-P max-procs

  Run up to max-procs processes at a time;
share|improve this answer

To avoid the error message and keep it simple:

mv *.* ./new_Folder

will do the same thing but avoid the error message (unless you have dots in your folder names I guess).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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