2

This question already has an answer here:

Under the current directory I have a number of files, and one directory. I would like to move all files to the sub directory:

mv ./* subdir/
cannot move ./subdir to a subdirectory of itself...

The warning is harmless but it makes mv return 1, therefore it's not possible to determine whether other files have been moved.

cp could help but I have some large files to move and it's not efficient enough.

Scripting would seem to work too, but I'd prefer a one liner if there is any.

marked as duplicate by Gilles shell Jun 30 '15 at 21:37

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    If you're happy to use bash, you can turn on extglob (shopt -s extglob) and use mv ./!(subdir) subdir/ – camh Jun 30 '15 at 7:56
  • thanks for closing a question which deverses an answer different from the "duplicate". go ahead and delete this question so that other users will never find an answer here. – Howard Jul 1 '15 at 5:17
  • is this what unix.se has become? over-moderation without careful consideration? I think I should stop contributing here. – Howard Jul 1 '15 at 5:25
  • 2
    Do the answers on the other question not solve this problem? They seem perfect. Having good answers here isn't a reason not to close as a duplicate, we can always merge them – Michael Mrozek Jul 1 '15 at 5:47
  • @Howard I don't understand. What's the problem here? The questions are clearly duplicates. That doesn't mean that this question is "useless". Dupes are good, they act as signposts and help people find the answer they are looking for. Please don't deface your posts. – terdon Jul 1 '15 at 8:34
1

You can do it with find:

$ find -maxdepth 1 -not -name subdir -print0 | xargs -0 mv -t subdir

Where:

  • -maxdepth 1 restricts the find traversal to the current directory (not a POSIX option, but e.g. available in GNU find)
  • -print0 tells find to terminate lines with 0 bytes - thus, making the command work with unusual filenames (e.g. ones containing newlines), also not POSIX, but provided by e.g. GNU find
  • -0 tells xargs about the 0 bytes - again, not POSIX, but e.g. understood by e.g. GNU xargs
  • -t instructs mv that the first argument is the target (not the last) - this is ideal for this use case - like before, option is not in POSIX, but e.g. implemented by GNU mv
0

You can try yet another more concise form, just like this one:

mv `ls -A |grep -v <subdir>` <subdir>

Here backslash characters stand for command substitution, i.e. mv will be executed with an output from command placed into backslashes as part of its arguments.

  • This has multiple issues: It does not work with filenames that contain whitespace. The grep pattern 'subdir' is expanded by the shell and thus breaks when there are multiple directories/files matching it. The last 'subdir' also potentially matches more files/directories than just 'subdir'. The command breaks when the current working directory contains many files such that the argument vector limit is reached. – maxschlepzig Jun 30 '15 at 11:44
  • @maxschlepzig thanks for the note, I have slightly corrected formatting – Aleksey Dashevsky Jul 1 '15 at 19:26

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