How to move all files from current directory to upper directory?

134

93

How to move all files from current directory to upper directory in linux?

I tried something like mv *.*, but it doesn't work.

asksuperuser

Posted 2009-10-28T18:54:06.357

Reputation:

http://unix.stackexchange.com/a/251091/139312 – palindrom – 2015-12-23T08:46:53.547

I don't have enough rep to retag questions, but may I suggest [linux] [mv] [cwd] [files], or something similar? – Stephan202 – 2009-10-28T19:33:19.663

I have retagged this question per Stephan202's request. – eleven81 – 2009-10-28T19:35:01.267

Answers

204

The command you are looking for is

mv * .[^.]* ..

or (see below for more info):

(shopt -s dotglob; mv -- * ..)

Explanation: the mv command moves files and directories. The last argument to mv is the target (in this case the directory one step "up" in the tree, ..). The arguments before that are the source files and directories. The asterisk (*) is a wildcard which matches all files which do not start with a dot. Files that start with a dot (dotfiles) are "hidden". They are matched using the pattern .[^.]* (see edit below).

See the manpage which I linked for more information on mv.


Why .[^.]* instead of .* ?

As Chris Johnsen correctly points out: the pattern .* also matches . and ... Since you don't want to (and cannot) move those, it's better to use a pattern which matches any filename starting with a dot except those two. The pattern .[^.]* does just that: it matches any filename (1) starting with a dot (2) followed by a character which is not a dot (3) followed by zero or more arbitrary characters.

As Paggas points out, we'd also have to add the pattern .??* in order to match files starting with two dots. See his answer for an alternative solution using find.

Arjan's answer mentions shopt in order to avoid all those issues with dotfiles. But then there is still the problem with files starting with a dash. And it requires three commands. Still, I like the idea. I propose to use it like this:

(shopt -s dotglob; mv -- * ..)

This executes shopt in a subshell (thus no second call to shopt required) and uses -- so that files starting with a dash will not be interpreted as arguments to mv.

Stephan202

Posted 2009-10-28T18:54:06.357

Reputation: 5 946

Gives mv: rename .[^.]* to ../.[^.]*: No such file or directory – pal4life – 2014-06-19T00:14:40.350

Does the .[^.]* work on /bin/sh? – jdg – 2014-11-10T18:56:05.413

What if you are in the target directory? I used this and it worked: mv subdir/(*|.[^.]*) .. Any comments about that? – Tristan Jahier – 2015-03-30T14:28:40.920

didn't work for me ,"mv: cannot stat .[^.]*: no such file or directory" ? centos6 – Exlord – 2015-11-21T15:31:03.347

1

The correct three patterns are *, .[^.]* and ..?*. The second maybe .[!.]* for older (POSIX) shells. Also read

– None – 2016-05-01T07:06:24.970

This fails to copy any directories which already exist and are non-empty in the destination. 'mv -f' doesn't help. I don't think there's any way to force this, so I suspect I have to start by iterating over the files being copied and 'rm' them from the destination. If I'm doing that, then I may as well 'mv' the files one at a time while iterating too. – Jonathan Hartley – 2012-01-08T16:28:44.543

7Using .* might cause mv to produce warnings/errors about not being able to move . and ... You might try mv * .[^.]* .. instead. – Chris Johnsen – 2009-10-28T19:21:53.197

1@alain: you're welcome, and welcome to the site! (If (and only if) one of the posts here sufficiently answered your question, then you can mark it as such. That will get the poster 15 extra reputation points, and also give you 2 rep extra.) – Stephan202 – 2009-10-28T19:41:44.437

I really like the shopt solution running in a subshell :) – Paggas – 2009-10-29T20:04:19.917

2There is no harm in the * .* syntax -- including .. is only hazardous when used with chmod and chown and the "recurse" flag, ie chmod -R or chown -R. And in those cases, don't ever ever type chown .* or chmod .* -- chown the top directory in the path you're looking for and use -h (don't follow symbolic links). But, mv .. simply doesn't do anything so don't worry about it. – chris – 2009-11-06T04:16:50.837

45

Short answer: use

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

Long answer:

The command

mv * .* ..

will not work since .* can match . and ... But the command

mv * .[^.]* ..

will also not work, since .[^.]* won't match, e.g., ..filename! Instead, what I do is

mv * .[^.] .??* ..

which will match everything except . and ... * will match everything that doesn't start with a ., .[^.] will match all 2 character filenames starting with a dot except .., and .??* will match all filenames starting with a dot with at least 3 characters.

Better yet, you can use

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

which avoids the ugly glob hacks in mv * .[^.] .??* ..!

Paggas

Posted 2009-10-28T18:54:06.357

Reputation: 714

1This gives mv: illegal option -- t – pal4life – 2014-07-29T21:08:33.603

Could you explain what the -- {} + does? Or where I can find an answer to that question? That is the only magic left for me in this answer. – Bono – 2017-07-21T07:42:50.877

1Bono, the double dashes tells mv to stop looking for any further command options. The braces are a resulting filename. The plus sign says instead of running exec per result (ie. per filename), put as many results in a single exec as possible. For completeness, -t.. is telling move the target destination to move all of these files to. – isuldor – 2018-01-02T01:00:42.340

1Also, I forgot to note the importance of -- so that the command works correctly with file names starting with a dash. I have included -- in my find answer though. A more complete answer using globs is "mv -- * .[^.] .??* ..". – Paggas – 2009-10-28T20:45:23.853

+1: I came back to add ..?* to my comment, and you had already taken care of it. – Chris Johnsen – 2009-10-29T03:10:15.097

1What can possibly be wrong with trying to mv .. ? It simply does nothing and can't do anything. There are other commands where it can do something (chmod and chown) but mv and rm simply don't do anything to . or .. – chris – 2009-11-06T04:18:33.953

This did not work with .git/ folder ;( – Daniel T. Magnusson – 2013-04-27T13:27:55.677

14

Just for the sake of completeness, one can also tell the Bash shell to include hidden files, using shopt:

shopt -s dotglob
mv -- * ..
shopt -u dotglob

Arjan

Posted 2009-10-28T18:54:06.357

Reputation: 29 084

+1. Much cleaner. I think a slight improvement is in order, though. See the update to my answer. – Stephan202 – 2009-10-28T21:11:05.970

8

The mv lacks the functionality of moving hidden files when using * - so why not use copy instead?

cp -rf . ..

rm -rf *

No need to get into complex solutions of dotglobbing and using find commands.

Micky Martin

Posted 2009-10-28T18:54:06.357

Reputation: 81

Warning If you are moving in the same filesystem, in the biggest part of the cases you didn't really copy the files but only update the directory entries without moving inode or file contenents. See even [1]. With a cp and rm instead you are really copying all. – Hastur – 2016-01-22T10:22:53.483

7

rsync -a --remove-source-files . ..

rsync is an extremely powerful file copying tool, generally used for performing efficient incremental remote backups and mirrors.

With the above command, we are telling rsync to copy the content of . into ..

The switch -a enables recursion into . subdirectories and enables some other common options.

The switch --remove-source-files tells rsync to remove the source files after a successful copy, i.e. it makes rsync behave similarly to the mv command.

mrucci

Posted 2009-10-28T18:54:06.357

Reputation: 8 398

Nice, accepted solution gives me -bash: /bin/mv: Argument list too long error. This one works like the charm. – userlond – 2016-11-28T06:09:28.610

1A little more explanation would be nice. – ChrisF – 2013-01-20T12:20:30.697

Sure, hope it's more clear now. – mrucci – 2013-01-20T16:25:44.887

Note that --remove-source-files will not remove (synchronized) directories. – Dennis – 2013-10-25T18:22:46.343

2

This minimized command works on most modern shells:

\mv -- {,.{[^.],??}}* ..

Otherwise mentioned is a portable solution:

\mv -- * .[^.] .??* ..

Features:

  1. \ prevents aliases from altering mv undesirably.

  2. -- prevents filenames containing leading hyphens (-xyz) from being interpreted as command-line arguments.

  3. .[^.] matches all two character filenames beginning with . except ..

  4. .??* matches all other filenames three characters or longer.

Naive Implementations:

  1. The following skips hidden UNIX filenames, those that begin with . (.bashrc).

    mv * ..
    
  2. The following matches .. which recursively attempts to move every directory eventually all the way back to / into .. of the current working directory ($PWD or pwd). Never use.

    mv .* ..
    

dhchdhd

Posted 2009-10-28T18:54:06.357

Reputation: 198

2

Ultimately trying mv . will fail because mv won't be able to unlink the directory that you are currently in. You could mv * .. to move the files in the cwd.

DaveParillo

Posted 2009-10-28T18:54:06.357

Reputation: 13 402

2

mv * .??* ../.

* gets all not-dot files. .??* gets all . files at least three bytes long, which works for all legit ones. Anything left you probably want to rm rather than mv anyway.

The ../. doesn't offer any direct benefits over .. but when doing a move-to-directory it is a very good habit to get into, because it will fail, as you want, if there is something wrong with the path. For example, mv xyz bletch, where you think bletch is a directory, can be made more certain with mv xyz bletch/..

DigitalRoss

Posted 2009-10-28T18:54:06.357

Reputation: 2 968

2You might add .[^.] to get cover files like .a. – Chris Johnsen – 2009-10-29T03:12:15.093

There is no difference between ../ and ../. so I wouldn't bother typing the . after the slash. Also, in the case of mv and rm, it does no harm to include . and .. in the list, ie there isn't anything scary or wrong with mv * .* /path/to/file/, just as rm . or even -rf . doesn't do anything. – chris – 2009-11-06T04:21:27.600

2

It's more correct to use the pattern * .[!.] .??* than * .[^.] .??* since the former will also work with older shells such as ksh88:

mv -- * .[!.] .??* ..
  • -- prevents problems when you have a file name which begins with -
  • * matches all file names which don't begin with a .
  • there are no one character file names which begin with a . which you can/should move
  • .[!.] matches all two character file names which begin with a .
  • .??* matches all three character file names (or longer) which begin with a .

With ksh88, the file name pattern .[^.] will in fact match the file names .. (which always exists) and .^ (which probably doesn't exist), having an effect opposite to what is desired.

jrw32982 supports Monica

Posted 2009-10-28T18:54:06.357

Reputation: 145

0

Find and grep work too. This kind of structure might be helpful if you wanted to select files on more complicated criteria by modifying find and egrep.

find -maxdepth 1 | egrep '^./.'         # Returns all files

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..

user3192145

Posted 2009-10-28T18:54:06.357

Reputation: 1

0

I think the easiest solution for moving all files to its parent dir. would be

mv "`ls`" ../

or, If there are hidden files/directories

use:

mv "`ls -a`" ../ 2>/dev/null

Also, lets say you want to move the contents of some folder to one of its internal folder tony(say)

use:

mv "`ls -a`" /tony 2>/dev/null

Note:

"`ls -a`" 

To move the files that have spaces in it.

2>/dev/null

Is for suppressing the warning/error because ls -a would print the . and .. folder as well and you can't move or copy them. So for those folders it will show error (if we don't use 2>/dev/null) that it can't move them and the rest will be moved quite comfortably.

Best to avoid ls -a if there is no hidden files and just use ls.

Prabhat Kumar Singh

Posted 2009-10-28T18:54:06.357

Reputation: 111

Have you tried what will happen when you run mv $(ls -a)? That'd tap on the current directory and the directory below it, because ls -a will output .. as well. – Sami Laine – 2014-08-06T16:46:28.307

Thanks , @SamiLaine for the suggestion I have made the corrections. But mv ls -a ../ would have also worked as per need, Yes it will show those errors as I mentioned above but other than that it will move the required folders/files to the parent dir. – Prabhat Kumar Singh – 2014-08-08T10:45:39.887

This won't work for files with spaces. – kenorb – 2015-05-27T22:47:46.583

@kenorb you need to double quote the ls command in order to move files with spaces. I have made the required changes. Thanks for pointing out. – Prabhat Kumar Singh – 2018-04-04T09:48:29.723