15

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?

Amandasaurus
  • 31,471
  • 65
  • 192
  • 253
  • 3
    it works, it just prints an error message that it's unable to move new_directory into itself. – cas Sep 08 '09 at 21:49

9 Answers9

19

Your

mv * ./new_directory
command will actually work; it'll just print a warning that it can't move that directory into itself.
mibus
  • 816
  • 4
  • 5
  • 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 08 '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
11

A fast and dirty oneliner.

mv `ls -A | grep -v new_directory` ./new_directory
8

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.

Cian
  • 5,838
  • 1
  • 28
  • 40
  • 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 08 '09 at 09: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 08 '09 at 09:59
  • cool use of `find` - though I've definitely been on systems that don't have one, sadly :( – warren Sep 08 '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 08 '09 at 10:27
  • Yep, it appears to be http://www.opengroup.org/onlinepubs/009695399/utilities/find.html – Cian Sep 08 '09 at 10:29
  • then i've been on some systems that have had findutils (or similar) yoinked for whatever reason. Not saying it's good - but I've seen it happen – warren Sep 08 '09 at 11:48
  • @Cian: it's `-P` *max-procs* (uppercase), not `-p`. `-p` is a synonym for `--interactive`. – Cristian Ciupitu Sep 08 '09 at 19:18
6

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 '.'

Kenster
  • 2,152
  • 16
  • 16
2

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.

Javier
  • 9,268
  • 2
  • 24
  • 24
1

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.

warren
  • 18,369
  • 23
  • 84
  • 135
  • 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 08 '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 08 '09 at 16:15
1

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.
Niels Basjes
  • 2,196
  • 3
  • 19
  • 26
1

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;
Cristian Ciupitu
  • 6,396
  • 2
  • 42
  • 56
-1

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).